diff --git a/.gitignore b/.gitignore index d4f5c81..15a6fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ DerivedData .idea/ /TSTableView /TSTabView +/.project +/.gitignore diff --git a/Classes/TSUIKit/TSTableView/Private/TSTableViewContentHolder.m b/Classes/TSUIKit/TSTableView/Private/TSTableViewContentHolder.m index 9032999..ec97933 100644 --- a/Classes/TSUIKit/TSTableView/Private/TSTableViewContentHolder.m +++ b/Classes/TSUIKit/TSTableView/Private/TSTableViewContentHolder.m @@ -33,7 +33,7 @@ #import "TSUtils.h" #import "TSDefines.h" - + /** @abstract Selection rectangle view @@ -77,6 +77,17 @@ - (void)initialize [self addSubview:_imageView]; self.selectionColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.25f]; + + //mark: add hide TSTableViewSelection event + UITapGestureRecognizer *hideEvent = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleHide:)]; + [self addGestureRecognizer:hideEvent]; +} + +- (void)handleHide:(UITapGestureRecognizer *)recognizer +{ + self.alpha = 0; + self.hidden = YES; + self.selectedItem = nil; } - (void)setSelectionColor:(UIColor *)selectionColor @@ -103,8 +114,6 @@ @interface TSTableViewContentHolder () @property (nonatomic, strong) TSTableViewSelection *rowSelectionView; @property (nonatomic, strong) TSTableViewSelection *columnSelectionView; -@property (nonatomic, strong) UITapGestureRecognizer *tapGestureRecognizer; - @end @implementation TSTableViewContentHolder @@ -164,8 +173,9 @@ - (void)initialize _reusableCells = [[NSMutableDictionary alloc] init]; _reusableRows = [[NSMutableArray alloc] init]; - _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureDidRecognized:)]; - [self addGestureRecognizer:_tapGestureRecognizer]; + //mark: remove TSTableViewContentHolder's tapGestureRecognizer +// _tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureDidRecognized:)]; +// [self addGestureRecognizer:_tapGestureRecognizer]; } - (TSTableViewSelection *)rowSelectionView @@ -390,8 +400,9 @@ - (void)updateRowsVisibility (topTreshold <= CGRectGetMaxY(row.frame) && CGRectGetMaxY(row.frame) <= bottomTreshold) || (CGRectGetMinY(row.frame) < topTreshold && bottomTreshold < CGRectGetMaxY(row.frame))) { - if(!row.rowView) + if(!row.rowView){ [self rowWillAppear:row atPath:[NSIndexPath indexPathWithIndex:i]]; + } } else { @@ -782,12 +793,13 @@ - (NSIndexPath *)pathToSelectedColumn } #pragma mark - Selection - -- (void)tapGestureDidRecognized:(UITapGestureRecognizer *)recognizer +//mark: 响应左侧面板的点击事件 +- (void)tapExpandPanelRecognized:(UITapGestureRecognizer *)recognizer { if(_allowRowSelection) { CGPoint pos = [recognizer locationInView:self]; + pos.x += self.frame.origin.x;//mark: 把事件发生的点偏移一个左侧面板宽度的距离 NSIndexPath *rowIndexPath = [self findRowAtPosition:pos parentRow:nil parentPowPath:nil]; if(rowIndexPath) diff --git a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandControlPanel.m b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandControlPanel.m index 5869df6..1eefbd0 100644 --- a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandControlPanel.m +++ b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandControlPanel.m @@ -32,7 +32,6 @@ #import "TSUtils.h" #import "TSDefines.h" - @interface TSTableViewExpandControlPanel () { NSMutableArray* _rows; @@ -116,8 +115,9 @@ - (void)addExpandButtonAtPath:(NSIndexPath *)rowPath expandRowView:(TSTableViewE UIImage *normalImage = [self.dataSource controlPanelExpandItemNormalBackgroundImage]; UIImage *selectedImage = [self.dataSource controlPanelExpandItemSelectedBackgroundImage]; CGFloat rowHeight = [self.dataSource heightForRowAtPath:rowPath]; - UIButton *expandBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, expandRow.frame.size.width, rowHeight)]; - expandBtn.autoresizingMask = UIViewAutoresizingFlexibleWidth; + UIButton *expandBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 24, rowHeight)]; +// expandBtn.backgroundColor = [UIColor colorWithRed:0 green:0.8 blue:0 alpha:0.3]; +// expandBtn.autoresizingMask = UIViewAutoresizingFlexibleWidth; expandBtn.showsTouchWhenHighlighted = [self.dataSource highlightControlsOnTap]; expandBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; expandBtn.contentVerticalAlignment = UIControlContentVerticalAlignmentBottom; @@ -168,7 +168,7 @@ - (void)loadSubrowsForRowAtPath:(NSIndexPath *)rowPath expandRowView:(TSTableVie NSInteger numberOfRows = [self.dataSource numberOfRowsAtPath:rowPath]; if(numberOfRows) { - CGFloat controlPanelExpandButtonWidth = [self.dataSource widthForExpandItem]; + CGFloat controlPanelExpandButtonWidth = [self.dataSource widthForExpandItem];//此宽度决定行头内容显示的宽度 UIImage *controlPanelExpandBackImage = [self.dataSource controlPanelExpandSectionBackgroundImage]; NSMutableArray *newRows = [[NSMutableArray alloc] init]; for(int j = 0; j < numberOfRows; ++j) @@ -192,6 +192,16 @@ - (void)loadSubrowsForRowAtPath:(NSIndexPath *)rowPath expandRowView:(TSTableVie rowView.lineLabel.textColor = [self.dataSource lineNumbersColor]; } [self addExpandButtonAtPath:subrowPath expandRowView:rowView]; + + //mark: 在TSTableViewExpandSection中添加一个label + NSString *rowhead = [self.dataSource rowHead:subrowPath]; + + //根据计算结果重新设置UILabel的尺寸 + CGSize size = [rowhead sizeWithFont:rowView.rowHeadLabel.font constrainedToSize:CGSizeMake(controlPanelExpandButtonWidth, rowView.rowHeadLabel.frame.size.height)]; + [rowView.rowHeadLabel setFrame:CGRectMake(rowView.rowHeadLabel.frame.origin.x, rowView.rowHeadLabel.frame.origin.y, size.width, rowView.rowHeadLabel.frame.size.height)]; + + rowView.rowHeadLabel.text = rowhead; + [self loadSubrowsForRowAtPath:subrowPath expandRowView:rowView]; [newRows addObject:rowView]; @@ -570,7 +580,8 @@ - (void)updateLayoutForRows:(NSArray *)rows totalHeight:(CGFloat *)totalHeight nestingLevel:(NSInteger *)maxNestingLevel { - CGFloat controlPanelExpandButtonWidth = [self.dataSource widthForExpandItem]; + CGFloat controlPanelExpandButtonWidth = [self.dataSource widthForExpandItem];//此宽度决定整个controlPanel的宽度 + CGFloat nestingSize = [self.dataSource expandNestingSize]; CGFloat maxWidth = 0; NSInteger maxNestLevel = 0; for(int i = 0; i < rows.count; ++i) @@ -584,7 +595,7 @@ - (void)updateLayoutForRows:(NSArray *)rows { [self updateLayoutForRows:row.subrows yOffset:totalRowHeight - xOffset:totalRowWidth + xOffset:nestingSize totalWidth:&totalRowWidth totalHeight:&totalRowHeight nestingLevel:&nestingLevel]; @@ -600,20 +611,20 @@ - (void)updateLayoutForRows:(NSArray *)rows if(nestingLevel > maxNestLevel) maxNestLevel = nestingLevel; } - *totalWidth += maxWidth; + *totalWidth = maxWidth + nestingSize; *maxNestingLevel += maxNestLevel; } - (void)adjustRowWidthTo:(CGFloat)rowWidth forRows:(NSArray *)rows { - CGFloat controlPanelExpandButtonWidth = [self.dataSource widthForExpandItem]; + CGFloat nestingSize = [self.dataSource expandNestingSize]; for(int i = 0; i < rows.count; ++i) { TSTableViewExpandSection *row = rows[i]; row.frame = CGRectMake(row.frame.origin.x, row.frame.origin.y, rowWidth, row.frame.size.height); if(row.subrows.count) { - [self adjustRowWidthTo:rowWidth - controlPanelExpandButtonWidth forRows:row.subrows]; + [self adjustRowWidthTo:rowWidth - nestingSize forRows:row.subrows]; } } } diff --git a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.h b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.h index 3be9ade..28b74c7 100644 --- a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.h +++ b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.h @@ -36,6 +36,7 @@ @property (nonatomic, strong) UIButton *expandButton; @property (nonatomic, strong, readonly) UILabel *lineLabel; @property (nonatomic, strong, readonly) UIImageView *backgroundImage; +@property (nonatomic, strong, readonly) UILabel *rowHeadLabel; - (void)setLineNumber:(NSInteger)lineNumber; diff --git a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.m b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.m index 687155f..8c08bda 100644 --- a/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.m +++ b/Classes/TSUIKit/TSTableView/Private/TSTableViewExpandSection.m @@ -34,7 +34,7 @@ @interface TSTableViewExpandSection () @property (nonatomic, strong, readwrite) UILabel *lineLabel; @property (nonatomic, strong, readwrite) UIImageView *backgroundImage; - +@property (nonatomic, strong, readwrite) UILabel *rowHeadLabel; @end @@ -69,7 +69,7 @@ - (UILabel *)lineLabel _lineLabel.backgroundColor = [UIColor colorWithWhite:0 alpha:0.1f]; _lineLabel.textAlignment = NSTextAlignmentCenter; _lineLabel.textColor = [UIColor blackColor]; - _lineLabel.font = [UIFont italicSystemFontOfSize:7]; + _lineLabel.font = [UIFont italicSystemFontOfSize:6.5]; _lineLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; _lineLabel.layer.cornerRadius = 3; _lineLabel.layer.masksToBounds = YES; @@ -79,6 +79,25 @@ - (UILabel *)lineLabel return _lineLabel; } +- (UILabel *)rowHeadLabel +{ + if(!_rowHeadLabel) + { + _rowHeadLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0,self.bounds.size.width, _rowHeight)]; + _rowHeadLabel.backgroundColor = [UIColor clearColor]; + _rowHeadLabel.font = [UIFont systemFontOfSize:14.0f]; + _rowHeadLabel.textColor = [UIColor darkGrayColor]; + +// _rowHeadLabel.textAlignment = NSTextAlignmentCenter; +// _rowHeadLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; +// _rowHeadLabel.layer.cornerRadius = 3; +// _rowHeadLabel.layer.masksToBounds = YES; + [self addSubview:_rowHeadLabel]; + [self updateRowHeadLabelLayout]; + } + return _rowHeadLabel; +} + - (UIImageView *)backgroundImage { if(!_backgroundImage) @@ -112,6 +131,15 @@ - (void)updateLineLabelLayout } } +- (void)updateRowHeadLabelLayout +{ + if(_rowHeadLabel) + { +// [self.rowHeadLabel sizeThatFits:CGSizeMake(200, 20)]; + self.rowHeadLabel.frame = CGRectMake(25, 0, self.rowHeadLabel.frame.size.width + 40, self.rowHeadLabel.frame.size.height); + } +} + - (void)setExpandButton:(UIButton *)expandButton { if(_expandButton) diff --git a/Classes/TSUIKit/TSTableView/Private/TSTableViewHeaderPanel.m b/Classes/TSUIKit/TSTableView/Private/TSTableViewHeaderPanel.m index 4693f0c..3c4f8c7 100644 --- a/Classes/TSUIKit/TSTableView/Private/TSTableViewHeaderPanel.m +++ b/Classes/TSUIKit/TSTableView/Private/TSTableViewHeaderPanel.m @@ -33,7 +33,6 @@ #import "TSUtils.h" #import "TSDefines.h" - @interface TSTableViewHeaderPanel () { NSMutableArray *_headerSections; diff --git a/Classes/TSUIKit/TSTableView/TSTableView.h b/Classes/TSUIKit/TSTableView/TSTableView.h index 12f9bf5..5564db3 100644 --- a/Classes/TSUIKit/TSTableView/TSTableView.h +++ b/Classes/TSUIKit/TSTableView/TSTableView.h @@ -30,6 +30,258 @@ #import "TSTableViewDataSource.h" #import "TSTableViewDelegate.h" +/* Default appearance styles of TSTableView provided by TSTableViewModel */ +typedef enum { + kTSTableViewStyleDark, /* Dark color scheme is used for backgrounds and light colors for font */ + kTSTableViewStyleLight /* Light color scheme is used for backgrounds and dark colors for font */ +} TSTableViewStyle; + + +/** + @abstract Classes provided below implement prototype for TSTableViewDataSource. + It is optional part of TSTableView infrastructure, inluded as an example of possible data source implementation. + + This prototype provides enough flexibility for building custom TSTableView containers. + If you need something completly different you can always implement your own data source entity. + */ + +/**************************************************************************************************************************************/ + +/** TSColumn provides infromation about content and appearance of TSTableViewHederSectionView component. Initialization dictionary can contain values for properties specified in TSColumn interface. Example: + + ``` + NSDictionary *columnInfo = @{ + @"title" : @"Column 1", + @"subtitle" : @"This is first column", + @"subcolumns" : @[ + @{ @"title" : @"Subcolumn 1.1"}, + @{ @"title" : @"Subcolumn 1.2"} + ] + }; + ``` + */ +@interface TSColumn : NSObject + +/** Array of subcolumns/subsections. */ +@property (nonatomic, strong) NSArray *subcolumns; +/** Column title. */ +@property (nonatomic, strong) NSString *title; +/** Column details. */ +@property (nonatomic, strong) NSString *subtitle; +/** Column icon. */ +@property (nonatomic, strong) UIImage *icon; +/** Tint color for background. */ +@property (nonatomic, strong) UIColor *color; +/** Color for title. */ +@property (nonatomic, strong) UIColor *titleColor; +/** Color for details. */ +@property (nonatomic, strong) UIColor *subtitleColor; +/** Title font size. */ +@property (nonatomic, assign) CGFloat titleFontSize; +/** Details font size. */ +@property (nonatomic, assign) CGFloat subtitleFontSize; +/** Default (or initial) column width. */ +@property (nonatomic, assign) CGFloat defWidth; +/** Minimal column width. */ +@property (nonatomic, assign) CGFloat minWidth; +/** Maximal column width. */ +@property (nonatomic, assign) CGFloat maxWidth; +/** Column header height. */ +@property (nonatomic, assign) CGFloat headerHeight; +/** Text aligment used for title and details. */ +@property (nonatomic, assign) NSTextAlignment textAlignment; + +/** Create column with title. + @param title Title displayed in column header. + */ ++ (id)columnWithTitle:(NSString *)title; +/** Create column with title and subcolumns. + @param title Title displayed in column header. + @param sublolumns Array of TSColumn objects or NSString titles for subcolumns. + */ ++ (id)columnWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns; +/** Create column with dictionary which define content and properties of TSColumn. + @param info Dictionary containes values for named properties of TSColumn. + + ``` + NSDictionary *columnInfo = @{ + @"title" : @"Column 1", + @"subtitle" : @"This is first column", + @"subcolumns" : @[ + @{ @"title" : @"Subcolumn 1.1"}, + @{ @"title" : @"Subcolumn 1.2"} + ] + }; + ``` + */ ++ (id)columnWithDictionary:(NSDictionary *)info; + +/** Initialize column with title. + @param title Title displayed in column header. + */ +- (id)initWithTitle:(NSString *)title; +/** Initialize column with title and subcolumns. + @param title Title displayed in column header. + @param sublolumns Array of TSColumn objects or NSString titles for subcolumns. + */ +- (id)initWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns; +/** Initialize column with dictionary which define content and properties of TSColumn. + @param info Dictionary containes values for named properties of TSColumn. + + ``` + NSDictionary *columnInfo = @{ + @"title" : @"Column 1", + @"subtitle" : @"This is first column", + @"subcolumns" : @[ + @{ @"title" : @"Subcolumn 1.1"}, + @{ @"title" : @"Subcolumn 1.2"} + ] + }; + ``` + */ +- (id)initWithDictionary:(NSDictionary *)info; + +@end + +/**************************************************************************************************************************************/ + +/** TSRow provides information about table row content (cells) and hierarchy (subrows). */ +@interface TSRow : NSObject + +//mark: 添加行头属性 +@property (nonatomic, strong) NSString *rowHead; + +/** Array of TSCell objects. */ +@property (nonatomic, strong) NSArray *cells; +/** Array of TSRow objects (subrows). */ +@property (nonatomic, strong) NSMutableArray *subrows; + +/** Create row with set of cells. + @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). + */ ++ (id)rowWithCells:(NSArray *)cells; +/** Create row with set of cells. + @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). + @param subrows Array may contain mix of TSRow and NSArray objects. + */ ++ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows; ++ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows andRowHead:(NSString*)rowHead; + +/** Create row with dictionary which define content TSRow. + @param info Dictionary containes values for cells and subrows. + + ``` + NSDictionary *rowInfo = @{ + @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } + ], + @"subrows" : @[ + @{ @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } ] }, + @{ @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } ] }, + ] + }; + ``` + */ ++ (id)rowWithDictionary:(NSDictionary *)info; + +/** Initialize row with set of cells. + @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). + */ +- (id)initWithCells:(NSArray *)cells; +- (id)initWithCells:(NSArray *)cells andRowHead:(NSString*)rowHead; + +/** Initialize row with set of cells. + @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). + @param subrows Array may contain mix of TSRow and NSArray objects. + */ +- (id)initWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows andRowHead:(NSString*)rowHead; +/** Initialize row with dictionary which define content TSRow. + @param info Dictionary containes values for cells and subrows. + + ``` + NSDictionary *rowInfo = @{ + @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } + ], + @"subrows" : @[ + @{ @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } ] }, + @{ @"cells" : @[ + @{ @"value" : @1 }, + @{ @"value" : @1 }, + @{ @"value" : @1 } ] }, + ] + }; + ``` + */ +- (id)initWithDictionary:(NSDictionary *)info; + +@end + +/**************************************************************************************************************************************/ + +/** TSCell provides inforamation about TableView cell content. */ +@interface TSCell : NSObject + +/** Value for cell (NSString, NSNumber etc). */ +@property (nonatomic, strong) NSObject *value; +/** Details text for cell. */ +@property (nonatomic, strong) NSString *details; +/** Icon image for cell. */ +@property (nonatomic, strong) UIImage *icon; +/** Text aligment in cell. */ +@property (nonatomic, assign) NSTextAlignment textAlignment; +/** Text color. */ +@property (nonatomic, strong) UIColor *textColor; +/** Details color. */ +@property (nonatomic, strong) UIColor *detailsColor; + +/** Create cell with value. + @param value NSObject value type. Provide NSString, NSNumber etc arguments. + */ ++ (id)cellWithValue:(NSObject *)value; +/** Create cell with dictionary which define content and properties of TSCell. + @param info Dictionary containes values for named properties of TSCell. + + ``` + NSDictionary *cellInfo = @{ + @"value" : @1, + @"icon" : @"image.png" + }; + ``` + */ ++ (id)cellWithDictionary:(NSDictionary *)info; +/** Initialize cell with value. + @param value NSObject value type. Provide NSString, NSNumber etc arguments. + */ +- (id)initWithValue:(NSObject *)value; +/** Initialize cell with dictionary which define content and properties of TSCell. + @param info Dictionary containes values for named properties of TSCell. + + ``` + NSDictionary *cellInfo = @{ + @"value" : @1, + @"icon" : @"image.png" + }; + ``` + */ +- (id)initWithDictionary:(NSDictionary *)info; + +@end + + /** @abstract TSTableView is UI component for displaying multicolumns tabular data. It supports hierarchical rows and columns structure. Component optimized to display big sets of data: row and cell views are cached internaly and reused during scrolling/expanding. @@ -60,7 +312,6 @@ @interface TSTableView : UIView -@property (nonatomic, weak) id dataSource; @property (nonatomic, weak) id delegate; /** @@ -155,6 +406,50 @@ */ @property (nonatomic, strong) UIColor *expandPanelBackgroundColor; +/** Readonly array with information about columns hierarchy. */ +@property (nonatomic, strong, readonly) NSArray *columns; +/** Readonly array with information about rows data. */ +@property (nonatomic, strong, readonly) NSArray *rows; + +/** TSTableView style choosen during initialization */ +@property (nonatomic, assign, readonly) TSTableViewStyle tableStyle; +/** Row height. + @warning This data model use fixed row height. Override TSTableViewModel to provide varied row height functionality. TSTableView support rows with varied height. + */ +@property (nonatomic, assign) CGFloat heightForRow; +/** Width of one nesting level in expand panel. Total panel width would be widthForExpandItem * maxRowNestingLevel. */ +@property (nonatomic, assign) CGFloat widthForExpandItem; + + +/** Initialize with array of columns and rows. + @param columns Array can contain objects of mixed types (TSColumn, NSDictionary, NSString). TSColumn objects would be constructed if needed. + @param rows Array can contain objects of mixed types (TSRow, NSDictionary, NSString). TSRow objects would be constructed if needed. + */ +- (void)setColumns:(NSArray *)columns andRows:(NSArray *)rows; +/** Initialize with rows data. Columns hierarchy remains the same. + @param rows Array can contain objects of mixed types (TSRow, NSDictionary, NSString). TSRow objects would be constructed if needed. + */ +- (void)setRows:(NSArray *)rows; +/** Insert new row at specified path. TSTableView would be notified about changes in data model. + @param rowInfo TSRow instance with new data. + @param indexPath Insert positon. + */ +- (void)insertRow:(TSRow *)rowInfo atPath:(NSIndexPath *)indexPath; +/** Remove row at specified path. TSTableView would be notified about changes in data model. + @param indexPath Remove positon. + */ +- (void)removeRowAtPath:(NSIndexPath *)indexPath; +/** Replace (update) information in row at specified path. TSTableView would be notified about changes in data model. + @param indexPath Updated row positon. + @param rowInfo TSRow instance with new data. + */ +- (void)replcaceRowAtPath:(NSIndexPath *)indexPath withRow:(TSRow *)rowInfo; + +/** + @abstract //mark: add init with style + */ +- (id)initWithFrame:(CGRect)frame andStyle:(TSTableViewStyle)style; + /** @abstract Reload content. Both columns and rows are updated */ @@ -238,3 +533,5 @@ - (void)removeRowsAtPathes:(NSArray *)pathes animated:(BOOL)animated; @end + + diff --git a/Classes/TSUIKit/TSTableView/TSTableView.m b/Classes/TSUIKit/TSTableView/TSTableView.m index a624595..9e719e9 100644 --- a/Classes/TSUIKit/TSTableView/TSTableView.m +++ b/Classes/TSUIKit/TSTableView/TSTableView.m @@ -34,6 +34,20 @@ #import "TSUtils.h" #import "TSDefines.h" +#import "TSTableViewCell.h" +#import "TSTableViewHeaderSectionView.h" + +#import + +#define MIN_COLUMN_WIDTH 64 +#define MAX_COLUMN_WIDTH 512 +#define DEF_COLUMN_WIDTH 128 +#define DEF_COLUMN_HEADER_HEIGHT 32 +#define DEF_ROW_HEIGHT 28 +#define DEF_EXPAND_ITEM_WIDTH 8 +#define MAX_ROWHEAD_WIDTH 68 +#define DEF_EXPAND_NESTING_SIZE 12 + #define DEF_TABLE_CONTENT_ADDITIONAL_SIZE 32 #define DEF_TABLE_MIN_COLUMN_WIDTH 64 #define DEF_TABLE_MAX_COLUMN_WIDTH 512 @@ -46,8 +60,22 @@ - (void)selectColumnAtPath:(NSIndexPath *)columnPath animated:(BOOL)animated int @end -@interface TSTableView () - +@interface TSTableView () +{ + NSMutableDictionary *_cachedHeaderSectionBackgroundImages; + NSMutableDictionary *_cachedCellBackgroundImages; + UIImage *_cachedGeneralBackgroundImage; + UIImage *_cachedExpandSectionBackgroundImage; + UIImage *_cachedExpandItemNormalBackgroundImage; + UIImage *_cachedExpandItemSelectedBackgroundImage; + NSMutableArray *_columns; + NSMutableArray *_bottomEndColumns; + NSMutableArray *_rows; + + //add TopLeftCorner touch event + CGPoint _lastTouchPos; + BOOL _changingColumnSize; +} @property (nonatomic, strong) TSTableViewHeaderPanel *tableHeader; @property (nonatomic, strong) TSTableViewExpandControlPanel *tableControlPanel; @@ -87,6 +115,43 @@ - (id)initWithFrame:(CGRect)frame return self; } +//mark: add init with style +- (id)initWithFrame:(CGRect)frame andStyle:(TSTableViewStyle)style +{ + if(self = [super initWithFrame:frame]) + { + [self initialize]; + _tableStyle = style; + if(_tableStyle == kTSTableViewStyleLight) + { + self.lineNumbersColor = [UIColor blackColor]; + self.backgroundColor = [UIColor colorWithWhite:0.922 alpha:1]; + } + else + { + self.lineNumbersColor = [UIColor lightGrayColor]; + self.backgroundColor = [UIColor colorWithWhite:0.12 alpha:1]; + } + + _heightForRow = DEF_ROW_HEIGHT; + _widthForExpandItem = DEF_EXPAND_ITEM_WIDTH; + + _rows = [[NSMutableArray alloc] init]; + _columns = [[NSMutableArray alloc] init]; + _bottomEndColumns = [[NSMutableArray alloc] init]; + _cachedHeaderSectionBackgroundImages = [[NSMutableDictionary alloc] init]; + _cachedCellBackgroundImages = [[NSMutableDictionary alloc] init]; + + self.headerBackgroundImage = [self generalBackgroundImage]; + self.expandPanelBackgroundImage = [self generalBackgroundImage]; + self.topLeftCornerBackgroundImage = [self generalBackgroundImage]; + self.expandItemNormalBackgroundImage = [self expandItemNormalBackgroundImage]; + self.expandItemSelectedBackgroundImage = [self expandItemSelectedBackgroundImage]; + self.expandSectionBackgroundImage = [self expandSectionBackgroundImage]; + } + return self; +} + - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) @@ -123,17 +188,17 @@ - (void)initialize _tableContentHolder.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; _tableContentHolder.contentHolderDelegate = self; [self addSubview: _tableContentHolder]; -} - -- (void)setDataSource:(id)dSource -{ - VerboseLog(); - _dataSource = dSource; + + //mark: 给左侧的ExpandControlPanel添加点击事件。让其响应为选中某一行。代替原来点击TSTableViewContentHolder的事件响应。 + UITapGestureRecognizer *tapExpandPanel = [[UITapGestureRecognizer alloc] initWithTarget:_tableContentHolder action:@selector(tapExpandPanelRecognized:)]; + [_tableControlPanel addGestureRecognizer:tapExpandPanel]; + _tableHeader.dataSource = (id)self; _tableControlPanel.dataSource = (id)self; _tableContentHolder.dataSource = (id)self; } + #pragma mark - Getters & Setters - (NSInteger)maxNestingLevel @@ -266,11 +331,61 @@ - (UIImageView *)topLeftCornerBackgroundImageView if(!_topLeftCornerBackgroundImageView) { _topLeftCornerBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _tableControlPanel.frame.size.width, _tableHeader.frame.size.height)]; + _topLeftCornerBackgroundImageView.userInteractionEnabled = YES; [self addSubview:_topLeftCornerBackgroundImageView]; + [self addSlideButtonToTopLeftCorner:_topLeftCornerBackgroundImageView]; } return _topLeftCornerBackgroundImageView; } +#pragma mark - Slide Button +//mark: addSlideButtonToTopLeftCorner +- (void)addSlideButtonToTopLeftCorner:(UIImageView *)section +{ + VerboseLog(); + CGFloat slideBtnWidth = 10; + UIButton *slideBtn = [[UIButton alloc] initWithFrame:CGRectMake(section.frame.size.width - slideBtnWidth, 0, slideBtnWidth, section.frame.size.height)]; + slideBtn.showsTouchWhenHighlighted = [self highlightControlsOnTap]; + [slideBtn addTarget:self action:@selector(slideTouchBegin:withEvent:) forControlEvents:UIControlEventTouchDown]; + [slideBtn addTarget:self action:@selector(slideTouch:withEvent:) forControlEvents:UIControlEventAllTouchEvents]; + [slideBtn addTarget:self action:@selector(slideTouchEnd:withEvent:) forControlEvents:UIControlEventTouchUpInside]; + [slideBtn addTarget:self action:@selector(slideTouchEnd:withEvent:) forControlEvents:UIControlEventTouchUpOutside]; + + slideBtn.backgroundColor = [UIColor colorWithRed:0.81 green:0.81 blue:0.81 alpha:0.85]; + slideBtn.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleHeight; + [section addSubview:slideBtn]; +} + +- (void)slideTouchBegin:(UIButton *)sender withEvent:(UIEvent *)event +{ + VerboseLog(); + _changingColumnSize = YES; + _lastTouchPos = [[[event allTouches] anyObject] locationInView:self]; +} + +- (void)slideTouchEnd:(UIButton *)sender withEvent:(UIEvent *)event +{ + VerboseLog(); + _changingColumnSize = NO; +} + +- (void)slideTouch:(UIButton *)sender withEvent:(UIEvent *)event +{ + VerboseLog(); + if(_changingColumnSize) + { + CGPoint centerPoint = [[[event allTouches] anyObject] locationInView:self]; + CGFloat delta = centerPoint.x - _lastTouchPos.x; + _widthForExpandItem += delta; + if (_widthForExpandItem < DEF_EXPAND_ITEM_WIDTH) { + _widthForExpandItem = DEF_EXPAND_ITEM_WIDTH; + } + [self reloadData]; + [self reloadRowsData]; + _lastTouchPos = centerPoint; + } +} + #pragma mark - Layout @@ -484,25 +599,6 @@ - (NSIndexPath *)pathToSelectedColumn return [_tableContentHolder pathToSelectedColumn]; } -#pragma mark - Provide TSTableViewDataSource functionality - -- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector -{ - NSMethodSignature *signature = [super methodSignatureForSelector:aSelector]; - if(!signature) - signature = [(id)self.dataSource methodSignatureForSelector:aSelector]; - - return signature; -} - -- (void)forwardInvocation:(NSInvocation *)anInvocation -{ - if ([self.dataSource respondsToSelector:[anInvocation selector]]) - [anInvocation invokeWithTarget:self.dataSource]; - else - [super forwardInvocation:anInvocation]; -} - #pragma mark - TSTableViewAppearanceCoordinator - (BOOL)isRowExpanded:(NSIndexPath *)indexPath @@ -581,40 +677,15 @@ - (CGFloat)offsetForColumnAtPath:(NSIndexPath *)columnPath return [_tableHeader offsetForColumnAtPath:columnPath]; } -- (CGFloat)defaultWidthForColumnAtIndex:(NSInteger)index -{ - if(self.dataSource && [self.dataSource respondsToSelector:@selector(defaultWidthForColumnAtIndex:)]) - { - return [self.dataSource defaultWidthForColumnAtIndex:index]; - } - return DEF_TABLE_DEF_COLUMN_WIDTH; -} - -- (CGFloat)minimalWidthForColumnAtIndex:(NSInteger)index -{ - if(self.dataSource && [self.dataSource respondsToSelector:@selector(minimalWidthForColumnAtIndex:)]) - { - return [self.dataSource minimalWidthForColumnAtIndex:index]; - } - return DEF_TABLE_MIN_COLUMN_WIDTH; -} -- (CGFloat)maximalWidthForColumnAtIndex:(NSInteger)index -{ - if(self.dataSource && [self.dataSource respondsToSelector:@selector(maximalWidthForColumnAtIndex:)]) - { - return [self.dataSource maximalWidthForColumnAtIndex:index]; - } - return DEF_TABLE_MAX_COLUMN_WIDTH; -} - (TSTableViewCell *)cellViewForRowAtPath:(NSIndexPath *)indexPath cellIndex:(NSInteger)index { - return [self.dataSource tableView:self cellViewForRowAtPath:indexPath cellIndex:index]; + return [self tableView:self cellViewForRowAtPath:indexPath cellIndex:index]; } - (TSTableViewHeaderSectionView *)headerSectionViewForColumnAtPath:(NSIndexPath *)indexPath { - return [self.dataSource tableView:self headerSectionViewForColumnAtPath:indexPath]; + return [self tableView:self headerSectionViewForColumnAtPath:indexPath]; } #pragma mark - Modify content @@ -657,4 +728,1507 @@ - (void)removeRowsAtPathes:(NSArray *)pathes animated:(BOOL)animated NSAssert(FALSE, @"Not implemented"); } +/**************************************************************************************************************************************/ +#pragma mark - Create background images + +- (NSString *)keyForColor:(UIColor *)color +{ + if(!color) return @""; + const CGFloat *rgba = CGColorGetComponents(color.CGColor); + return [NSString stringWithFormat:@"%d%d%d%d", (char)(rgba[0] * 255), (char)(rgba[1] * 255), (char)(rgba[2] * 255), (char)(rgba[3] * 255)]; +} + +- (UIImage *)cellBackgroundImageWithTintColor:(UIColor *)color +{ + NSString *key = [self keyForColor:color]; + UIImage *image = _cachedCellBackgroundImages[key]; + if(!image) + { + if(_tableStyle == kTSTableViewStyleDark) + image = [self darkCellBackgroundImageWithTintColor:color]; + else + image = [self lightCellBackgroundImageWithTintColor:color]; + _cachedCellBackgroundImages[key] = image; + } + return image; +} + +- (UIImage *)headerSectionBackgroundImageWithTintColor:(UIColor *)color +{ + NSString *key = [self keyForColor:color]; + UIImage *image = _cachedHeaderSectionBackgroundImages[key]; + if(!image) + { + if(_tableStyle == kTSTableViewStyleDark) + image = [self darkHeaderSectionBackgroundImageWithTintColor:color]; + else + image = [self lightHeaderSectionBackgroundImageWithTintColor:color]; + _cachedHeaderSectionBackgroundImages[key] = image; + } + return image; +} + +- (UIImage *)expandSectionBackgroundImage +{ + if(!_cachedExpandSectionBackgroundImage) + { + if(_tableStyle == kTSTableViewStyleDark) + _cachedExpandSectionBackgroundImage = [self darkExpandSectionBackgroundImage]; + else + _cachedExpandSectionBackgroundImage = [self lightExpandSectionBackgroundImage]; + } + return _cachedExpandSectionBackgroundImage; +} + +- (UIImage *)expandItemNormalBackgroundImage +{ + if(!_cachedExpandItemNormalBackgroundImage) + { + if(_tableStyle == kTSTableViewStyleDark) + _cachedExpandItemNormalBackgroundImage = [self darkExpandItemNormalBackgroundImage]; + else + _cachedExpandItemNormalBackgroundImage = [self lightExpandItemNormalBackgroundImage]; + } + return _cachedExpandItemNormalBackgroundImage; +} + +- (UIImage *)expandItemSelectedBackgroundImage +{ + if(!_cachedExpandItemSelectedBackgroundImage) + { + if(_tableStyle == kTSTableViewStyleDark) + _cachedExpandItemSelectedBackgroundImage = [self darkExpandItemSelectedBackgroundImage]; + else + _cachedExpandItemSelectedBackgroundImage = [self lightExpandItemSelectedBackgroundImage]; + } + return _cachedExpandItemSelectedBackgroundImage; +} + +- (UIImage *)generalBackgroundImage +{ + if(!_cachedGeneralBackgroundImage) + { + if(_tableStyle == kTSTableViewStyleDark) + _cachedGeneralBackgroundImage = [self darkGeneralBackgroundImage]; + else + _cachedGeneralBackgroundImage = [self lightGeneralBackgroundImage]; + } + return _cachedGeneralBackgroundImage; +} + +#pragma mark - Create background images for Light style + +- (UIImage *)lightCellBackgroundImageWithTintColor:(UIColor *)color +{ + UIColor *topColor = (color ? color : [UIColor whiteColor]); + UIColor *bottomColor = (color ? color : [UIColor whiteColor]); + UIColor *topBorderColor = [UIColor whiteColor]; + UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor whiteColor]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + +- (UIImage *)lightHeaderSectionBackgroundImageWithTintColor:(UIColor *)color +{ + UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; + UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.9f alpha:1.0f]); + UIColor *topBorderColor = [UIColor whiteColor]; + UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor whiteColor]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; + + CGFloat lineWidth = 8; + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - lineWidth/2, 0) + endPoint:CGPointMake(rect.size.width - lineWidth/2, rect.size.height - 0.5f) + color:lineColor.CGColor + lineWidth:lineWidth]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + +- (UIImage *)lightExpandSectionBackgroundImage +{ + UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; + UIColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; + UIColor *topBorderColor = [UIColor whiteColor]; + UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor whiteColor]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; + + CGFloat lineWidth = 8; + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(lineWidth/2, 0) + endPoint:CGPointMake(lineWidth/2, rect.size.height - 0.5f) + color:lineColor.CGColor + lineWidth:lineWidth]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + + +- (UIImage *)lightExpandItemNormalBackgroundImage +{ + CGFloat expandItemWidth = DEF_EXPAND_NESTING_SIZE; + CGFloat rowHeight = [self heightForRow]; + CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGFloat lineWithd = 8; + NSArray *points = @[ + [NSValue valueWithCGPoint:CGPointMake(lineWithd + 1, CGRectGetMidY(rect) - lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth - 5, CGRectGetMidY(rect) - lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect))], + + [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth - 5, CGRectGetMidY(rect) + lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd + 1, CGRectGetMidY(rect) + lineWithd/2)] + ]; + + [TSUtils drawPolygonInContext:context points:points + fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor + strokeColor:[UIColor clearColor].CGColor + strokeSize:0]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; +} + +- (UIImage *)lightExpandItemSelectedBackgroundImage +{ + CGFloat expandItemWidth = DEF_EXPAND_NESTING_SIZE; + CGFloat rowHeight = [self heightForRow]; + CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGFloat lineWithd = 8; + + NSArray *points = @[ + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd/2, CGRectGetMaxY(rect) - 2)], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth - lineWithd/2, CGRectGetMaxY(rect) - 14)], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + 3 * lineWithd/2, CGRectGetMaxY(rect) - 14)] + ]; + + [TSUtils drawPolygonInContext:context points:points + fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor + strokeColor:[UIColor clearColor].CGColor + strokeSize:0]; + + NSArray *points1 = @[ + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect))], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect) - 6)], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd/2, CGRectGetMaxY(rect))], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect) - 6)], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect))] + ]; + + [TSUtils drawPolygonInContext:context points:points1 + fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor + strokeColor:[UIColor clearColor].CGColor + strokeSize:0]; + + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (UIImage *)lightGeneralBackgroundImage +{ + UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; + UIColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; + UIColor *topBorderColor = [UIColor whiteColor]; + UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor whiteColor]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; + + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + +#pragma mark - Create background images for Dark Style + +- (UIImage *)darkCellBackgroundImageWithTintColor:(UIColor *)color +{ + UIColor *topColor = (color ? color : [UIColor colorWithWhite:0.2f alpha:1.0f]); + UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.15f alpha:1.0f]); + UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; + + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + +- (UIImage *)darkHeaderSectionBackgroundImageWithTintColor:(UIColor *)color +{ + UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; + UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.15f alpha:1.0f]); + UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; + + CGFloat lineWidth = 8; + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - lineWidth/2, 0) + endPoint:CGPointMake(rect.size.width - lineWidth/2, rect.size.height - 0.5f) + color:lineColor.CGColor + lineWidth:lineWidth]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/4]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(2, rect.size.width/2, 2, rect.size.width/2) resizingMode:UIImageResizingModeStretch]; +} + +- (UIImage *)darkExpandSectionBackgroundImage +{ + UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; + UIColor *bottomColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; + UIColor *topBorderColor = [UIColor colorWithWhite:0.3f alpha:1.0f]; + UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *lineColor = [UIColor colorWithWhite:0 alpha:0.15f]; + + CGFloat lineWidth = 8; + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(lineWidth/2, 0) + endPoint:CGPointMake(lineWidth/2, rect.size.height - 0.5f) + color:lineColor.CGColor + lineWidth:lineWidth]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + + +- (UIImage *)darkExpandItemNormalBackgroundImage +{ + CGFloat expandItemWidth = [self widthForExpandItem]; + CGFloat rowHeight = [self heightForRow]; + CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGFloat lineWithd = 8; + NSArray *points = @[ + [NSValue valueWithCGPoint:CGPointMake(lineWithd , CGRectGetMidY(rect) - lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect) - lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect) + lineWithd/2)], + [NSValue valueWithCGPoint:CGPointMake(lineWithd , CGRectGetMidY(rect) + lineWithd/2)] + ]; + + CGMutablePathRef path = CGPathCreateMutable(); + for(int i = 0; i < points.count; ++i) + { + NSValue *pointVal = points[i]; + CGPoint point = [pointVal CGPointValue]; + if(i == 0) + CGPathMoveToPoint(path, NULL, point.x, point.y); + else + CGPathAddLineToPoint(path, NULL, point.x, point.y); + } + CGFloat radius = 8; + CGPathAddEllipseInRect(path, NULL, CGRectMake(expandItemWidth + lineWithd/2 - radius, CGRectGetMidY(rect) - radius, 2*radius, 2*radius)); + + CGPathCloseSubpath(path); + + + CGContextSaveGState(context); + + CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:0.15].CGColor); + CGContextAddPath(context, path); + CGContextFillPath(context); + + CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:1 alpha:0.1].CGColor); + CGFloat innerRadius = 3.5f; + CGContextAddEllipseInRect(context, CGRectMake(expandItemWidth + lineWithd/2 - innerRadius, CGRectGetMidY(rect) - innerRadius, 2*innerRadius, 2*innerRadius)); + CGContextStrokePath(context); + CGContextRestoreGState(context); + + CGPathRelease(path); + + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (UIImage *)darkExpandItemSelectedBackgroundImage +{ + CGFloat expandItemWidth = [self widthForExpandItem]; + CGFloat rowHeight = [self heightForRow]; + CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGFloat lineWithd = 8; + NSArray *points = @[ + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect))], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMidY(rect))], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMidY(rect))], + [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect))] + ]; + + CGMutablePathRef path = CGPathCreateMutable(); + for(int i = 0; i < points.count; ++i) + { + NSValue *pointVal = points[i]; + CGPoint point = [pointVal CGPointValue]; + if(i == 0) + CGPathMoveToPoint(path, NULL, point.x, point.y); + else + CGPathAddLineToPoint(path, NULL, point.x, point.y); + } + CGFloat radius = 8; + CGPathAddEllipseInRect(path, NULL, CGRectMake(expandItemWidth + lineWithd/2 - radius, CGRectGetMidY(rect) - radius, 2*radius, 2*radius)); + + CGPathCloseSubpath(path); + + + CGContextSaveGState(context); + + CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:0.15].CGColor); + CGContextAddPath(context, path); + CGContextFillPath(context); + + CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0.185 alpha:1].CGColor); + CGFloat innerRadius = 3.5f; + CGContextAddEllipseInRect(context, CGRectMake(expandItemWidth + lineWithd/2 - innerRadius, CGRectGetMidY(rect) - innerRadius, 2*innerRadius, 2*innerRadius)); + CGContextFillPath(context); + CGContextRestoreGState(context); + + CGPathRelease(path); + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return image; +} + +- (UIImage *)darkGeneralBackgroundImage +{ + UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; + UIColor *bottomColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; + UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; + UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; + UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; + + CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); + CGContextRef context = UIGraphicsGetCurrentContext(); + + [TSUtils drawLinearGradientInContext:context + rect:rect + startColor:topColor.CGColor + endColor:bottomColor.CGColor]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, 0) + color:topBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, rect.size.height - 0.5f) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:bottomBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(rect.size.width - 0.5f, 0) + endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) + color:rightBorderColor.CGColor + lineWidth:0.5]; + [TSUtils drawLineInContext:context + startPoint:CGPointMake(0, 0) + endPoint:CGPointMake(0, rect.size.height - 0.5f) + color:leftBorderColor.CGColor + lineWidth:0.5]; + + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; + //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; +} + +#pragma mark - TSTableViewDataSource + + +/* + //mark: 根据path取行头内容 + */ +- (NSString *)rowHead:(NSIndexPath *)indexPath +{ + TSRow *row; + NSMutableArray *rows = _rows; + for(int i = 0; i < indexPath.length; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + row = rows[index]; + rows = row.subrows; + } + return [row rowHead]; +} + +- (NSInteger)numberOfColumns +{ + VerboseLog(); + return [self calcNumberOfColumns:_columns]; +} + +- (NSInteger)calcNumberOfColumns:(NSArray *)columns +{ + VerboseLog(); + NSInteger columnsCount = columns.count; + for(TSColumn *column in columns) + { + if(column.subcolumns.count) + { + columnsCount += [self calcNumberOfColumns:column.subcolumns] - 1; + } + } + return columnsCount; +} + +- (NSInteger)numberOfRows +{ + VerboseLog(); + return [self calcNumberOfRows:_rows]; +} + +- (NSInteger)calcNumberOfRows:(NSArray *)rows +{ + VerboseLog(); + NSInteger rowsCount = rows.count; + for(TSRow *row in rows) + { + rowsCount += [self calcNumberOfRows:row.subrows]; + } + return rowsCount; +} + +- (NSInteger)numberOfColumnsAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(@"%@", indexPath); + if(indexPath == nil) + return _columns.count; + TSColumn *column = [self columnAtPath:indexPath]; + return column.subcolumns.count; +} + +- (NSInteger)numberOfRowsAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + if(indexPath == nil) + return _rows.count; + TSRow *row = [self rowAtPath:indexPath]; + return row.subrows.count; +} + +- (CGFloat)heightForRowAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + return _heightForRow; +} + +- (CGFloat)heightForHeaderSectionAtPath:(NSIndexPath *)columnPath +{ + VerboseLog(); + TSColumn *columnInfo = [self columnAtPath:columnPath]; + return columnInfo.headerHeight; +} + +- (CGFloat)defaultWidthForColumnAtIndex:(NSInteger)index +{ + TSColumn *columnInfo = [self columnAtIndex:index]; + return columnInfo.defWidth; +} + +- (CGFloat)minimalWidthForColumnAtIndex:(NSInteger)index +{ + TSColumn *columnInfo = [self columnAtIndex:index]; + return columnInfo.minWidth; +} + +- (CGFloat)maximalWidthForColumnAtIndex:(NSInteger)index +{ + TSColumn *columnInfo = [self columnAtIndex:index]; + return columnInfo.maxWidth; +} + +- (CGFloat)widthForExpandItem +{ + VerboseLog(); + return _widthForExpandItem; +} + +- (void)widthForExpandItem:(CGFloat)width +{ + _widthForExpandItem = width; +} + +- (CGFloat)expandNestingSize +{ + return DEF_EXPAND_NESTING_SIZE; +} + +//mark: 单元格点击事件处理。调用协议中的方法,让其动作给实现协议的类处理。 +-(void)tapTableViewCell:(UITapGestureRecognizer *)recognizer +{ + TSTableViewCell *cell = (TSTableViewCell*)recognizer.view; + NSString *value = cell.textLabel.text; + + if(self.delegate && [self.delegate respondsToSelector:@selector(tableView:tapCellView:cellValue:)]) + { + [self.delegate tableView:self tapCellView:cell cellValue:value]; + } + + if(self.delegate && [self.delegate respondsToSelector:@selector(cellClickWithRowPath:colIndex:cellValue:)]) + { + NSIndexPath *rowPath = cell.rowPath; + NSString *pathstr = rowPath.description; + NSString *pre = @"path ="; + NSString *suff = @"}"; + NSRange preRange = [pathstr rangeOfString:pre]; + NSUInteger preIndex = preRange.location + preRange.length; + NSRange suffRange = [pathstr rangeOfString:suff]; + NSUInteger suffIndex = suffRange.location; + NSRange rang = NSMakeRange(preIndex+1, suffIndex-preIndex-1); + NSString *row = [pathstr substringWithRange:rang]; + NSInteger col = cell.colIndex; + + [self.delegate cellClickWithRowPath:row colIndex:col cellValue:value]; + } +} + +- (TSTableViewCell *)tableView:(TSTableView *)tableView cellViewForRowAtPath:(NSIndexPath *)indexPath cellIndex:(NSInteger)index +{ + VerboseLog(); + NSString * const kReuseCellId = @"TSTableViewCell"; + TSCell *cellInfo = [self cellAtRowPath:indexPath atIndex:index]; + TSTableViewCell *cell = [tableView dequeueReusableCellViewWithIdentifier:kReuseCellId]; + if(!cell){ + cell = [[TSTableViewCell alloc] initWithReuseIdentifier:kReuseCellId]; + cell.rowPath = indexPath; + cell.colIndex = index; + + //mark: add TSTableViewCell UITapGestureRecognizer + UITapGestureRecognizer *tapCell = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapTableViewCell:)]; + [cell addGestureRecognizer:tapCell]; + } + + TSColumn *columnInfo = [self columnAtIndex:index]; + if(columnInfo.titleColor) + { + cell.textLabel.textColor = columnInfo.titleColor; + } + else + { + if(_tableStyle == kTSTableViewStyleDark) + cell.textLabel.textColor = [UIColor grayColor]; + else + cell.textLabel.textColor = [UIColor darkGrayColor]; + } + + if(cellInfo.value) + { + cell.textLabel.text = [cellInfo.value description]; + cell.textLabel.textAlignment = cellInfo.textAlignment; + if(cellInfo.textColor) + cell.textLabel.textColor = cellInfo.textColor; + } + if(cellInfo.details) + { + cell.detailsLabel.text = cellInfo.details; + cell.detailsLabel.textAlignment = cellInfo.textAlignment; + if(cellInfo.detailsColor) + cell.detailsLabel.textColor = cellInfo.detailsColor; + } + if(cellInfo.icon) + cell.iconView.image = cellInfo.icon; + + // Color values and proportions below just came up from my head, there is no special logic for this... it just looks fine, that's all + if(columnInfo.color) + { + CGFloat color = 0.9f + 0.1f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); + CGColorRef colorRef = columnInfo.color.CGColor; + const CGFloat *rgb = CGColorGetComponents(colorRef); + cell.backgroundImageView.image = [self cellBackgroundImageWithTintColor:[UIColor colorWithRed:color * rgb[0] green:color * rgb[1] blue:color * rgb[2] alpha:1]]; + } + else + { + CGFloat color; + if(_tableStyle == kTSTableViewStyleDark) + color = 0.16f + 0.04f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); + else + color = 0.9f + 0.1f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); + cell.backgroundImageView.image = [self cellBackgroundImageWithTintColor:[UIColor colorWithWhite:color alpha:1]]; + } + return cell; +} + +- (TSTableViewHeaderSectionView *)tableView:(TSTableView *)tableView headerSectionViewForColumnAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + TSColumn *column = [self columnAtPath:indexPath]; + TSTableViewHeaderSectionView *section = [[TSTableViewHeaderSectionView alloc] init]; + + if(_tableStyle == kTSTableViewStyleDark) + { + section.textLabel.layer.shadowColor = [UIColor blackColor].CGColor; + section.textLabel.textColor = [UIColor grayColor]; + } + else + { + section.textLabel.textColor = [UIColor darkGrayColor]; + } + section.backgroundImageView.image = [self headerSectionBackgroundImageWithTintColor:column.color]; + + if(column.title) + { + section.textLabel.text = column.title; + section.textLabel.textAlignment = column.textAlignment; + } + if(column.subtitle) + { + section.detailsLabel.text = column.subtitle; + section.detailsLabel.textAlignment = column.textAlignment; + } + if(column.icon) + section.iconView.image = column.icon; + if(column.titleColor) + section.textLabel.textColor = column.titleColor; + if(column.subtitleColor) + section.detailsLabel.textColor = column.subtitleColor; + if(column.titleFontSize) + section.textLabel.font = [UIFont boldSystemFontOfSize:column.titleFontSize]; + if(column.subtitleFontSize) + section.detailsLabel.font = [UIFont boldSystemFontOfSize:column.subtitleFontSize]; + + return section; +} + + +- (void)setColumns:(NSArray *)columns andRows:(NSArray *)rows +{ + VerboseLog(); + [_columns removeAllObjects]; + [_bottomEndColumns removeAllObjects]; + [_rows removeAllObjects]; + + for(id columnInfo in columns) + { + if([columnInfo isKindOfClass:[TSColumn class]]) + { + [_columns addObject:columnInfo]; + } + else if([columnInfo isKindOfClass:[NSString class]]) + { + [_columns addObject:[[TSColumn alloc] initWithTitle:columnInfo]]; + } + else if([columnInfo isKindOfClass:[NSDictionary class]]) + { + [_columns addObject:[TSColumn columnWithDictionary:columnInfo]]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + [self addLeafColumnsFrom:[_columns lastObject]]; + } + CGFloat max = 0.0; + for(id rowInfo in rows) + { + if([rowInfo isKindOfClass:[TSRow class]]) + { + TSRow *row = (TSRow*)rowInfo; + [self setExpandItemWidth:row maxWidth:&max]; + [_rows addObject:rowInfo]; + } + else if([rowInfo isKindOfClass:[NSArray class]]) + { + [_rows addObject:[[TSRow alloc] initWithCells:rowInfo]];//TODO: 此分支不能加行头! + } + else if([rowInfo isKindOfClass:[NSDictionary class]]) + { + TSRow *row = [TSRow rowWithDictionary:rowInfo]; + [self setExpandItemWidth:row maxWidth:&max]; + [_rows addObject:row]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + [self reloadData]; +} + + + //mark: 根据内容动态调整行头大小 +-(void)setExpandItemWidth:(TSRow *)row maxWidth:(CGFloat*)max +{ + NSString *head = row.rowHead; + + if(head !=nil){ + CGSize size = [head sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(MAXFLOAT, MAXFLOAT)]; + CGFloat width = size.width + 20; + if (width > *max) { + *max = width; + } + if (*max < MAX_ROWHEAD_WIDTH && *max > DEF_EXPAND_ITEM_WIDTH) { + _widthForExpandItem = *max; + }else if(width >= MAX_ROWHEAD_WIDTH){ + _widthForExpandItem = MAX_ROWHEAD_WIDTH; + } + } +} + +- (void)addLeafColumnsFrom:(TSColumn *)parentColumn +{ + if(parentColumn.subcolumns.count == 0) + { + [_bottomEndColumns addObject:parentColumn]; + } + else + { + for(TSColumn *column in parentColumn.subcolumns) + { + [self addLeafColumnsFrom:column]; + } + } +} + +- (void)setRows:(NSArray *)rows +{ + VerboseLog(); + [_rows removeAllObjects]; + + for(id rowInfo in rows) + { + if([rowInfo isKindOfClass:[TSRow class]]) + { + [_rows addObject:rowInfo]; + } + else if([rowInfo isKindOfClass:[NSArray class]]) + { + [_rows addObject:[[TSRow alloc] initWithCells:rowInfo]]; + } + else if([rowInfo isKindOfClass:[NSDictionary class]]) + { + [_rows addObject:[TSRow rowWithDictionary:rowInfo]]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + [self reloadRowsData]; +} + +- (TSRow *)rowAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + TSRow *row; + NSArray *rows = _rows; + for(int i = 0; i < indexPath.length; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + row = rows[index]; + rows = row.subrows; + } + return row; +} + +- (TSColumn *)columnAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + TSColumn *column; + NSArray *columns = _columns; + for(int i = 0; i < indexPath.length; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + column = columns[index]; + columns = column.subcolumns; + } + return column; +} + +- (TSCell *)cellAtRowPath:(NSIndexPath *)rowPath atIndex:(NSInteger)index +{ + VerboseLog(); + TSRow *row = [self rowAtPath:rowPath]; + TSCell *cell = row.cells[index]; + return cell; +} + +- (TSColumn *)columnAtIndex:(NSInteger)index +{ + VerboseLog(@"index = %d",index); + + return [_bottomEndColumns objectAtIndex:index]; +} + +// Find specified column recursevly in TSColumn hierarchy +- (TSColumn *)findColumnAtIndex:(NSInteger *)index inColumns:(NSArray *)columns +{ + TSColumn *found; + for (int i = 0; i < columns.count; ++i) + { + TSColumn *column = columns[i]; + if(column.subcolumns.count == 0) + { + if(*index == 0) + return column; + --(*index); + } + else + { + found = [self findColumnAtIndex:index inColumns:column.subcolumns]; + if(found) break; + } + } + return found; +} + + +#pragma mark - Modify content + +- (void)insertRow:(TSRow *)rowInfo atPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + TSRow *row; + NSMutableArray *rows = _rows; + for(int i = 0; i < indexPath.length - 1; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + row = rows[index]; + rows = row.subrows; + } + NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; + [rows insertObject:rowInfo atIndex:lastIndex]; + [self insertRowAtPath:indexPath animated:YES]; +} + +- (void)removeRowAtPath:(NSIndexPath *)indexPath +{ + VerboseLog(); + TSRow *row; + NSMutableArray *rows = _rows; + for(int i = 0; i < indexPath.length - 1; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + row = rows[index]; + rows = row.subrows; + } + NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; + [rows removeObjectAtIndex:lastIndex]; + [self removeRowAtPath:indexPath animated:YES]; +} + +- (void)replcaceRowAtPath:(NSIndexPath *)indexPath withRow:(TSRow *)rowInfo +{ + VerboseLog(); + TSRow *row; + NSMutableArray *rows = _rows; + for(int i = 0; i < indexPath.length - 1; ++i) + { + NSInteger index = [indexPath indexAtPosition:i]; + row = rows[index]; + rows = row.subrows; + } + NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; + [rows replaceObjectAtIndex:lastIndex withObject:rowInfo]; + [self updateRowAtPath:indexPath]; +} + +@end + + +@implementation TSColumn + ++ (id)columnWithTitle:(NSString *)title +{ + return [[TSColumn alloc] initWithTitle:title]; +} + ++ (id)columnWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns +{ + return [[TSColumn alloc] initWithTitle:title andSubcolumns:sublolumns]; +} + ++ (id)columnWithDictionary:(NSDictionary *)info +{ + return [[TSColumn alloc] initWithDictionary:info]; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"%@ - %@", [super description], self.title]; +} + +- (id)initWithTitle:(NSString *)title +{ + if(self = [super init]) + { + _title = title; + _minWidth = MIN_COLUMN_WIDTH; + _maxWidth = MAX_COLUMN_WIDTH; + _defWidth = DEF_COLUMN_WIDTH; + _headerHeight = DEF_COLUMN_HEADER_HEIGHT; + _textAlignment = NSTextAlignmentCenter; + } + return self; +} + +- (id)initWithTitle:(NSString *)title andSubcolumns:(NSArray *)subcolumns +{ + if(self = [super init]) + { + _title = title; + _minWidth = MIN_COLUMN_WIDTH; + _maxWidth = MAX_COLUMN_WIDTH; + _defWidth = DEF_COLUMN_WIDTH; + _headerHeight = DEF_COLUMN_HEADER_HEIGHT; + _textAlignment = NSTextAlignmentCenter; + + NSMutableArray *columns = [[NSMutableArray alloc] initWithCapacity:subcolumns.count]; + for(id subcolumn in subcolumns) + { + if([subcolumn isKindOfClass:[TSColumn class]]) + { + [columns addObject:subcolumn]; + } + else if([subcolumn isKindOfClass:[NSString class]]) + { + [columns addObject:[[TSColumn alloc] initWithTitle:title]]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + _subcolumns = columns; + } + return self; +} + +- (id)initWithDictionary:(NSDictionary *)info +{ + if(self = [super init]) + { + _title = info[@"title"]; + _subtitle = info[@"subtitle"]; + id iconVal = info[@"icon"]; + if([iconVal isKindOfClass:[UIImage class]]) + _icon = iconVal; + else if([iconVal isKindOfClass:[NSString class]]) + _icon = [UIImage imageNamed:iconVal]; + + id colorVal = info[@"color"]; + if([colorVal isKindOfClass:[UIColor class]]) + _color = colorVal; + else if([colorVal isKindOfClass:[NSString class]]) + _color = [TSUtils colorWithHexString:colorVal]; + + colorVal = info[@"titleColor"]; + if([colorVal isKindOfClass:[UIColor class]]) + _titleColor = colorVal; + else if([colorVal isKindOfClass:[NSString class]]) + _titleColor = [TSUtils colorWithHexString:colorVal]; + + colorVal = info[@"subtitleColor"]; + if([colorVal isKindOfClass:[UIColor class]]) + _subtitleColor = colorVal; + else if([colorVal isKindOfClass:[NSString class]]) + _subtitleColor = [TSUtils colorWithHexString:colorVal]; + + _titleFontSize = [info[@"titleFontSize"] floatValue]; + _subtitleFontSize = [info[@"subtitleFontSize"] floatValue]; + + _minWidth = MIN_COLUMN_WIDTH; + _maxWidth = MAX_COLUMN_WIDTH; + _defWidth = DEF_COLUMN_WIDTH; + _headerHeight = DEF_COLUMN_HEADER_HEIGHT; + _textAlignment = NSTextAlignmentCenter; + + NSString *textAligmentStr = info[@"textAlignment"]; + if(textAligmentStr) + _textAlignment = [textAligmentStr integerValue]; + + NSString *widthStr = info[@"minWidth"]; + if(widthStr) + _minWidth = [widthStr floatValue]; + + widthStr = info[@"maxWidth"]; + if(widthStr) + _maxWidth = [widthStr floatValue]; + + widthStr = info[@"defWidth"]; + if(widthStr) + _defWidth = [widthStr floatValue]; + + widthStr = info[@"headerHeight"]; + if(widthStr) + _headerHeight = [widthStr floatValue]; + + NSArray *subcolumns = info[@"subcolumns"]; + if(subcolumns.count) + { + NSMutableArray *tmpColumns = [[NSMutableArray alloc] initWithCapacity:subcolumns.count]; + for(id subcolumnInfo in subcolumns) + { + if([subcolumnInfo isKindOfClass:[NSString class]]) + { + [tmpColumns addObject:[[TSColumn alloc] initWithTitle:subcolumnInfo]]; + } + else if([subcolumnInfo isKindOfClass:[NSDictionary class]]) + { + [tmpColumns addObject:[[TSColumn alloc] initWithDictionary:subcolumnInfo]]; + } + else if([subcolumnInfo isKindOfClass:[TSColumn class]]) + { + [tmpColumns addObject:subcolumnInfo]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + _subcolumns = tmpColumns; + } + } + return self; +} + +@end + +/**************************************************************************************************************************************/ + +@implementation TSRow + ++ (id)rowWithCells:(NSArray *)cells +{ + return [[TSRow alloc] initWithCells:cells]; +} + ++ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows +{ + return [[TSRow alloc] initWithCells:cells andSubrows:subrows andRowHead:nil]; +} + ++ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows andRowHead:(NSString*)rowHead +{ + return [[TSRow alloc] initWithCells:cells andSubrows:subrows andRowHead:rowHead]; +} + ++ (id)rowWithDictionary:(NSDictionary *)info +{ + return [[TSRow alloc] initWithDictionary:info]; +} + +- (id)initWithCells:(NSArray *)cells +{ + return [self initWithCells:cells andSubrows:nil andRowHead:nil]; +} + +- (id)initWithCells:(NSArray *)cells andRowHead:(NSString*)rowHead +{ + return [self initWithCells:cells andSubrows:nil andRowHead:rowHead]; +} + +- (id)initWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows andRowHead:(NSString*)rowHead +{ + if(self = [super init]) + { + if (rowHead) { + _rowHead = rowHead; + } + if(cells) + { + NSMutableArray *tmpCells = [[NSMutableArray alloc] initWithCapacity:cells.count]; + for(id cell in cells) + { + if([cell isKindOfClass:[TSCell class]]) + { + [tmpCells addObject:cell]; + } + else + { + [tmpCells addObject:[[TSCell alloc] initWithValue:cell]]; + } + } + _cells = tmpCells; + } + + if(subrows) + { + NSMutableArray *tmpRows = [[NSMutableArray alloc] initWithCapacity:subrows.count]; + for(id row in subrows) + { + if([row isKindOfClass:[TSRow class]]) + { + [tmpRows addObject:row]; + } + else if([row isKindOfClass:[NSArray class]]) + { + [tmpRows addObject:[[TSRow alloc] initWithCells:row]]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + _subrows = tmpRows; + } + } + return self; +} + +- (id)initWithDictionary:(NSDictionary *)info +{ + if(self = [super init]) + { + //mark: rowHead 处理 + NSString *rowHead = info[@"rowHead"]; + if (rowHead) { + _rowHead = rowHead; + } + + NSArray *cells = info[@"cells"]; + if(cells) + { + NSMutableArray *tmpCells = [[NSMutableArray alloc] initWithCapacity:cells.count]; + for(id cellInfo in cells) + { + if([cellInfo isKindOfClass:[NSDictionary class]]) + { + [tmpCells addObject:[[TSCell alloc] initWithDictionary:cellInfo]]; + } + else if([cellInfo isKindOfClass:[TSCell class]]) + { + [tmpCells addObject:cellInfo]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + _cells = tmpCells; + } + + NSArray *subrows = info[@"subrows"]; + if(subrows) + { + NSMutableArray *tmpRows = [[NSMutableArray alloc] initWithCapacity:subrows.count]; + for(id rowInfo in subrows) + { + if([rowInfo isKindOfClass:[NSDictionary class]]) + { + [tmpRows addObject:[[TSRow alloc] initWithDictionary:rowInfo]]; + } + else if([rowInfo isKindOfClass:[TSRow class]]) + { + [tmpRows addObject:rowInfo]; + } + else + { + NSAssert(FALSE, @"Type is not supported"); + } + } + _subrows = tmpRows; + } + } + return self; +} + +@end + +/**************************************************************************************************************************************/ + +@implementation TSCell + ++ (id)cellWithValue:(NSObject *)value +{ + return [[TSCell alloc] initWithValue:value]; +} + ++ (id)cellWithDictionary:(NSDictionary *)info +{ + return [[TSCell alloc] initWithDictionary:info]; +} + +- (id)initWithValue:(NSObject *)value +{ + if(self = [super init]) + { + _textAlignment = NSTextAlignmentCenter; + _value = value; + } + return self; +} + +- (id)initWithDictionary:(NSDictionary *)info +{ + if(self = [super init]) + { + _value = info[@"value"]; + _details = info[@"details"]; + + id colorVal = info[@"textColor"]; + if([colorVal isKindOfClass:[UIColor class]]) + _textColor = colorVal; + else if([colorVal isKindOfClass:[NSString class]]) + _textColor = [TSUtils colorWithHexString:colorVal]; + + colorVal = info[@"detailsColor"]; + if([colorVal isKindOfClass:[UIColor class]]) + _detailsColor = colorVal; + else if([colorVal isKindOfClass:[NSString class]]) + _detailsColor = [TSUtils colorWithHexString:colorVal]; + + id iconVal = info[@"icon"]; + if([iconVal isKindOfClass:[UIImage class]]) + _icon = iconVal; + else if([iconVal isKindOfClass:[NSString class]]) + _icon = [UIImage imageNamed:iconVal]; + + _textAlignment = NSTextAlignmentCenter; + NSString *textAligmentStr = info[@"textAlignment"]; + if(textAligmentStr) + _textAlignment = [textAligmentStr integerValue]; + } + return self; +} + @end + + + diff --git a/Classes/TSUIKit/TSTableView/TSTableViewCell.h b/Classes/TSUIKit/TSTableView/TSTableViewCell.h index 506014c..e3e3601 100644 --- a/Classes/TSUIKit/TSTableView/TSTableViewCell.h +++ b/Classes/TSUIKit/TSTableView/TSTableViewCell.h @@ -43,6 +43,10 @@ @property (nonatomic, strong) UIImageView *iconView; @property (nonatomic, strong) UIImageView *backgroundImageView; +//mark: add row and col index +@property (nonatomic, strong) NSIndexPath *rowPath; +@property (nonatomic) NSInteger colIndex; + - (id)initWithReuseIdentifier:(NSString *)reuseId; /** diff --git a/Classes/TSUIKit/TSTableView/TSTableViewCell.m b/Classes/TSUIKit/TSTableView/TSTableViewCell.m index 83f496e..6f0dbf1 100644 --- a/Classes/TSUIKit/TSTableView/TSTableViewCell.m +++ b/Classes/TSUIKit/TSTableView/TSTableViewCell.m @@ -181,13 +181,13 @@ - (void)layoutSubviews - (void)prepareForReuse { - if(_detailsLabel) + if(_textLabel) { _textLabel.textAlignment = NSTextAlignmentCenter; _textLabel.font = [UIFont systemFontOfSize:14.0f]; _textLabel.textColor = [UIColor darkGrayColor]; } - if(_textLabel) + if(_detailsLabel) { _detailsLabel.textAlignment = NSTextAlignmentCenter; _detailsLabel.font = [UIFont systemFontOfSize:10.0f]; diff --git a/Classes/TSUIKit/TSTableView/TSTableViewDataSource.h b/Classes/TSUIKit/TSTableView/TSTableViewDataSource.h index 7016ee8..255cbe4 100644 --- a/Classes/TSUIKit/TSTableView/TSTableViewDataSource.h +++ b/Classes/TSUIKit/TSTableView/TSTableViewDataSource.h @@ -26,8 +26,8 @@ // THE SOFTWARE. #import +#include "TSTableViewCell.h" -@class TSTableViewCell; @class TSTableViewHeaderSectionView; @class TSTableView; @@ -70,6 +70,11 @@ */ - (TSTableViewHeaderSectionView *)tableView:(TSTableView *)tableView headerSectionViewForColumnAtPath:(NSIndexPath *)indexPath; +/* + mark: + */ +- (NSString *)rowHead:(NSIndexPath *)indexPath; + @optional /** @@ -83,6 +88,9 @@ where maxNesingLevel is maximal depth of subrows hierarchy */ - (CGFloat)widthForExpandItem; +- (void)widthForExpandItem:(CGFloat)width; + +- (CGFloat)expandNestingSize; /** @abstract Return default/prefered width for column at specified index diff --git a/Classes/TSUIKit/TSTableView/TSTableViewDelegate.h b/Classes/TSUIKit/TSTableView/TSTableViewDelegate.h index 046b798..b8c63e3 100644 --- a/Classes/TSUIKit/TSTableView/TSTableViewDelegate.h +++ b/Classes/TSUIKit/TSTableView/TSTableViewDelegate.h @@ -40,4 +40,8 @@ - (void)tableView:(TSTableView *)tableView widthDidChangeForColumnAtIndex:(NSInteger)columnIndex; - (void)tableView:(TSTableView *)tableView expandStateDidChange:(BOOL)expand forRowAtPath:(NSIndexPath *)rowPath; +//mark: 添加单元格点击处理协议 +- (void)tableView:(TSTableView *)tableView tapCellView:(TSTableViewCell*)cell cellValue:(NSString*)value; +- (void)cellClickWithRowPath:(NSString*)rowPath colIndex:(NSInteger)col cellValue:(NSString*)value; + @end diff --git a/Classes/TSUIKit/TSTableView/TSTableViewModel.h b/Classes/TSUIKit/TSTableView/TSTableViewModel.h deleted file mode 100644 index 07cec90..0000000 --- a/Classes/TSUIKit/TSTableView/TSTableViewModel.h +++ /dev/null @@ -1,332 +0,0 @@ -// -// TSTableViewModel.h -// TSUIKit -// -// Created by Viacheslav Radchenko on 8/14/13. -// -// The MIT License (MIT) -// Copyright © 2013 Viacheslav Radchenko -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import -#import "TSTableView.h" - -/** - @abstract Classes provided below implement prototype for TSTableViewDataSource. - It is optional part of TSTableView infrastructure, inluded as an example of possible data source implementation. - - This prototype provides enough flexibility for building custom TSTableView containers. - If you need something completly different you can always implement your own data source entity. - */ - -/**************************************************************************************************************************************/ - -/** TSColumn provides infromation about content and appearance of TSTableViewHederSectionView component. Initialization dictionary can contain values for properties specified in TSColumn interface. Example: - -``` - NSDictionary *columnInfo = @{ - @"title" : @"Column 1", - @"subtitle" : @"This is first column", - @"subcolumns" : @[ - @{ @"title" : @"Subcolumn 1.1"}, - @{ @"title" : @"Subcolumn 1.2"} - ] - }; -``` - */ -@interface TSColumn : NSObject - -/** Array of subcolumns/subsections. */ -@property (nonatomic, strong) NSArray *subcolumns; -/** Column title. */ -@property (nonatomic, strong) NSString *title; -/** Column details. */ -@property (nonatomic, strong) NSString *subtitle; -/** Column icon. */ -@property (nonatomic, strong) UIImage *icon; -/** Tint color for background. */ -@property (nonatomic, strong) UIColor *color; -/** Color for title. */ -@property (nonatomic, strong) UIColor *titleColor; -/** Color for details. */ -@property (nonatomic, strong) UIColor *subtitleColor; -/** Title font size. */ -@property (nonatomic, assign) CGFloat titleFontSize; -/** Details font size. */ -@property (nonatomic, assign) CGFloat subtitleFontSize; -/** Default (or initial) column width. */ -@property (nonatomic, assign) CGFloat defWidth; -/** Minimal column width. */ -@property (nonatomic, assign) CGFloat minWidth; -/** Maximal column width. */ -@property (nonatomic, assign) CGFloat maxWidth; -/** Column header height. */ -@property (nonatomic, assign) CGFloat headerHeight; -/** Text aligment used for title and details. */ -@property (nonatomic, assign) NSTextAlignment textAlignment; - -/** Create column with title. - @param title Title displayed in column header. - */ -+ (id)columnWithTitle:(NSString *)title; -/** Create column with title and subcolumns. - @param title Title displayed in column header. - @param sublolumns Array of TSColumn objects or NSString titles for subcolumns. - */ -+ (id)columnWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns; -/** Create column with dictionary which define content and properties of TSColumn. - @param info Dictionary containes values for named properties of TSColumn. - - ``` - NSDictionary *columnInfo = @{ - @"title" : @"Column 1", - @"subtitle" : @"This is first column", - @"subcolumns" : @[ - @{ @"title" : @"Subcolumn 1.1"}, - @{ @"title" : @"Subcolumn 1.2"} - ] - }; - ``` - */ -+ (id)columnWithDictionary:(NSDictionary *)info; - -/** Initialize column with title. - @param title Title displayed in column header. - */ -- (id)initWithTitle:(NSString *)title; -/** Initialize column with title and subcolumns. - @param title Title displayed in column header. - @param sublolumns Array of TSColumn objects or NSString titles for subcolumns. - */ -- (id)initWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns; -/** Initialize column with dictionary which define content and properties of TSColumn. - @param info Dictionary containes values for named properties of TSColumn. - - ``` - NSDictionary *columnInfo = @{ - @"title" : @"Column 1", - @"subtitle" : @"This is first column", - @"subcolumns" : @[ - @{ @"title" : @"Subcolumn 1.1"}, - @{ @"title" : @"Subcolumn 1.2"} - ] - }; - ``` - */ -- (id)initWithDictionary:(NSDictionary *)info; - -@end - -/**************************************************************************************************************************************/ - -/** TSRow provides information about table row content (cells) and hierarchy (subrows). */ -@interface TSRow : NSObject - -/** Array of TSCell objects. */ -@property (nonatomic, strong) NSArray *cells; -/** Array of TSRow objects (subrows). */ -@property (nonatomic, strong) NSMutableArray *subrows; - -/** Create row with set of cells. - @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). - */ -+ (id)rowWithCells:(NSArray *)cells; -/** Create row with set of cells. - @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). - @param subrows Array may contain mix of TSRow and NSArray objects. - */ -+ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows; -/** Create row with dictionary which define content TSRow. - @param info Dictionary containes values for cells and subrows. - - ``` - NSDictionary *rowInfo = @{ - @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } - ], - @"subrows" : @[ - @{ @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } ] }, - @{ @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } ] }, - ] - }; - ``` - */ -+ (id)rowWithDictionary:(NSDictionary *)info; -/** Initialize row with set of cells. - @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). - */ -- (id)initWithCells:(NSArray *)cells; -/** Initialize row with set of cells. - @param cells Array may contain mix of TSCell objects and any other NSObject value (which would be converted to TSCell). - @param subrows Array may contain mix of TSRow and NSArray objects. - */ -- (id)initWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows; -/** Initialize row with dictionary which define content TSRow. - @param info Dictionary containes values for cells and subrows. - - ``` - NSDictionary *rowInfo = @{ - @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } - ], - @"subrows" : @[ - @{ @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } ] }, - @{ @"cells" : @[ - @{ @"value" : @1 }, - @{ @"value" : @1 }, - @{ @"value" : @1 } ] }, - ] - }; - ``` - */ -- (id)initWithDictionary:(NSDictionary *)info; - -@end - -/**************************************************************************************************************************************/ - -/** TSCell provides inforamation about TableView cell content. */ -@interface TSCell : NSObject - -/** Value for cell (NSString, NSNumber etc). */ -@property (nonatomic, strong) NSObject *value; -/** Details text for cell. */ -@property (nonatomic, strong) NSString *details; -/** Icon image for cell. */ -@property (nonatomic, strong) UIImage *icon; -/** Text aligment in cell. */ -@property (nonatomic, assign) NSTextAlignment textAlignment; -/** Text color. */ -@property (nonatomic, strong) UIColor *textColor; -/** Details color. */ -@property (nonatomic, strong) UIColor *detailsColor; - -/** Create cell with value. - @param value NSObject value type. Provide NSString, NSNumber etc arguments. - */ -+ (id)cellWithValue:(NSObject *)value; -/** Create cell with dictionary which define content and properties of TSCell. - @param info Dictionary containes values for named properties of TSCell. - - ``` - NSDictionary *cellInfo = @{ - @"value" : @1, - @"icon" : @"image.png" - }; - ``` - */ -+ (id)cellWithDictionary:(NSDictionary *)info; -/** Initialize cell with value. - @param value NSObject value type. Provide NSString, NSNumber etc arguments. - */ -- (id)initWithValue:(NSObject *)value; -/** Initialize cell with dictionary which define content and properties of TSCell. - @param info Dictionary containes values for named properties of TSCell. - - ``` - NSDictionary *cellInfo = @{ - @"value" : @1, - @"icon" : @"image.png" - }; - ``` - */ -- (id)initWithDictionary:(NSDictionary *)info; - -@end - -/**************************************************************************************************************************************/ - -@class TSTableView; - -/* Default appearance styles of TSTableView provided by TSTableViewModel */ -typedef enum { - kTSTableViewStyleDark, /* Dark color scheme is used for backgrounds and light colors for font */ - kTSTableViewStyleLight /* Light color scheme is used for backgrounds and dark colors for font */ -} TSTableViewStyle; - -/** TSTableViewModel is a prototype for TSTableViewDataSource. - There are two default ready-to-use appearance styles kTSTableViewStyleDark and kTSTableViewStyleLight provided by TSTableViewModel. - */ -@interface TSTableViewModel : NSObject -{ - NSMutableArray *_columns; - NSMutableArray *_bottomEndColumns; - NSMutableArray *_rows; - TSTableView *_tableView; -} -/** Readonly array with information about columns hierarchy. */ -@property (nonatomic, strong, readonly) NSArray *columns; -/** Readonly array with information about rows data. */ -@property (nonatomic, strong, readonly) NSArray *rows; -/** Readonly reference to TSTableView instance managed by this model. */ -@property (nonatomic, strong, readonly) TSTableView *tableView; -/** TSTableView style choosen during initialization */ -@property (nonatomic, assign, readonly) TSTableViewStyle tableStyle; -/** Row height. - @warning This data model use fixed row height. Override TSTableViewModel to provide varied row height functionality. TSTableView support rows with varied height. - */ -@property (nonatomic, assign) CGFloat heightForRow; -/** Width of one nesting level in expand panel. Total panel width would be widthForExpandItem * maxRowNestingLevel. */ -@property (nonatomic, assign) CGFloat widthForExpandItem; - -/** Initialize instance of TSTableViewModel with corresponding TSTableView object and appearance style. - @param tableView Instance of TSTableView which would be managed by this data model. - @param style Appearance style of TSTableView. - */ -- (id)initWithTableView:(TSTableView *)tableView andStyle:(TSTableViewStyle)style; - -/** Initialize with array of columns and rows. - @param columns Array can contain objects of mixed types (TSColumn, NSDictionary, NSString). TSColumn objects would be constructed if needed. - @param rows Array can contain objects of mixed types (TSRow, NSDictionary, NSString). TSRow objects would be constructed if needed. - */ -- (void)setColumns:(NSArray *)columns andRows:(NSArray *)rows; -/** Initialize with rows data. Columns hierarchy remains the same. - @param rows Array can contain objects of mixed types (TSRow, NSDictionary, NSString). TSRow objects would be constructed if needed. - */ -- (void)setRows:(NSArray *)rows; -/** Insert new row at specified path. TSTableView would be notified about changes in data model. - @param rowInfo TSRow instance with new data. - @param indexPath Insert positon. - */ -- (void)insertRow:(TSRow *)rowInfo atPath:(NSIndexPath *)indexPath; -/** Remove row at specified path. TSTableView would be notified about changes in data model. - @param indexPath Remove positon. - */ -- (void)removeRowAtPath:(NSIndexPath *)indexPath; -/** Replace (update) information in row at specified path. TSTableView would be notified about changes in data model. - @param indexPath Updated row positon. - @param rowInfo TSRow instance with new data. - */ -- (void)replcaceRowAtPath:(NSIndexPath *)indexPath withRow:(TSRow *)rowInfo; - -@end diff --git a/Classes/TSUIKit/TSTableView/TSTableViewModel.m b/Classes/TSUIKit/TSTableView/TSTableViewModel.m deleted file mode 100644 index 3b08ecd..0000000 --- a/Classes/TSUIKit/TSTableView/TSTableViewModel.m +++ /dev/null @@ -1,1489 +0,0 @@ -// -// TSTableViewModel.m -// TSUIKit -// -// Created by Viacheslav Radchenko on 8/14/13. -// -// The MIT License (MIT) -// Copyright © 2013 Viacheslav Radchenko -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -#import "TSTableViewModel.h" -#import "TSTableView.h" -#import "TSTableViewCell.h" -#import "TSTableViewHeaderSectionView.h" -#import "TSDefines.h" -#import "TSUtils.h" - -#import - - -#define MIN_COLUMN_WIDTH 64 -#define MAX_COLUMN_WIDTH 512 -#define DEF_COLUMN_WIDTH 128 -#define DEF_COLUMN_HEADER_HEIGHT 32 -#define DEF_ROW_HEIGHT 28 -#define DEF_EXPAND_ITEM_WIDTH 24 - -@implementation TSColumn - -+ (id)columnWithTitle:(NSString *)title -{ - return [[TSColumn alloc] initWithTitle:title]; -} - -+ (id)columnWithTitle:(NSString *)title andSubcolumns:(NSArray *)sublolumns -{ - return [[TSColumn alloc] initWithTitle:title andSubcolumns:sublolumns]; -} - -+ (id)columnWithDictionary:(NSDictionary *)info -{ - return [[TSColumn alloc] initWithDictionary:info]; -} - -- (NSString *)description -{ - return [NSString stringWithFormat:@"%@ - %@", [super description], self.title]; -} - -- (id)initWithTitle:(NSString *)title -{ - if(self = [super init]) - { - _title = title; - _minWidth = MIN_COLUMN_WIDTH; - _maxWidth = MAX_COLUMN_WIDTH; - _defWidth = DEF_COLUMN_WIDTH; - _headerHeight = DEF_COLUMN_HEADER_HEIGHT; - _textAlignment = NSTextAlignmentCenter; - } - return self; -} - -- (id)initWithTitle:(NSString *)title andSubcolumns:(NSArray *)subcolumns -{ - if(self = [super init]) - { - _title = title; - _minWidth = MIN_COLUMN_WIDTH; - _maxWidth = MAX_COLUMN_WIDTH; - _defWidth = DEF_COLUMN_WIDTH; - _headerHeight = DEF_COLUMN_HEADER_HEIGHT; - _textAlignment = NSTextAlignmentCenter; - - NSMutableArray *columns = [[NSMutableArray alloc] initWithCapacity:subcolumns.count]; - for(id subcolumn in subcolumns) - { - if([subcolumn isKindOfClass:[TSColumn class]]) - { - [columns addObject:subcolumn]; - } - else if([subcolumn isKindOfClass:[NSString class]]) - { - [columns addObject:[[TSColumn alloc] initWithTitle:title]]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - _subcolumns = columns; - } - return self; -} - -- (id)initWithDictionary:(NSDictionary *)info -{ - if(self = [super init]) - { - _title = info[@"title"]; - _subtitle = info[@"subtitle"]; - id iconVal = info[@"icon"]; - if([iconVal isKindOfClass:[UIImage class]]) - _icon = iconVal; - else if([iconVal isKindOfClass:[NSString class]]) - _icon = [UIImage imageNamed:iconVal]; - - id colorVal = info[@"color"]; - if([colorVal isKindOfClass:[UIColor class]]) - _color = colorVal; - else if([colorVal isKindOfClass:[NSString class]]) - _color = [TSUtils colorWithHexString:colorVal]; - - colorVal = info[@"titleColor"]; - if([colorVal isKindOfClass:[UIColor class]]) - _titleColor = colorVal; - else if([colorVal isKindOfClass:[NSString class]]) - _titleColor = [TSUtils colorWithHexString:colorVal]; - - colorVal = info[@"subtitleColor"]; - if([colorVal isKindOfClass:[UIColor class]]) - _subtitleColor = colorVal; - else if([colorVal isKindOfClass:[NSString class]]) - _subtitleColor = [TSUtils colorWithHexString:colorVal]; - - _titleFontSize = [info[@"titleFontSize"] floatValue]; - _subtitleFontSize = [info[@"subtitleFontSize"] floatValue]; - - _minWidth = MIN_COLUMN_WIDTH; - _maxWidth = MAX_COLUMN_WIDTH; - _defWidth = DEF_COLUMN_WIDTH; - _headerHeight = DEF_COLUMN_HEADER_HEIGHT; - _textAlignment = NSTextAlignmentCenter; - - NSString *textAligmentStr = info[@"textAlignment"]; - if(textAligmentStr) - _textAlignment = [textAligmentStr integerValue]; - - NSString *widthStr = info[@"minWidth"]; - if(widthStr) - _minWidth = [widthStr floatValue]; - - widthStr = info[@"maxWidth"]; - if(widthStr) - _maxWidth = [widthStr floatValue]; - - widthStr = info[@"defWidth"]; - if(widthStr) - _defWidth = [widthStr floatValue]; - - widthStr = info[@"headerHeight"]; - if(widthStr) - _headerHeight = [widthStr floatValue]; - - NSArray *subcolumns = info[@"subcolumns"]; - if(subcolumns.count) - { - NSMutableArray *tmpColumns = [[NSMutableArray alloc] initWithCapacity:subcolumns.count]; - for(id subcolumnInfo in subcolumns) - { - if([subcolumnInfo isKindOfClass:[NSString class]]) - { - [tmpColumns addObject:[[TSColumn alloc] initWithTitle:subcolumnInfo]]; - } - else if([subcolumnInfo isKindOfClass:[NSDictionary class]]) - { - [tmpColumns addObject:[[TSColumn alloc] initWithDictionary:subcolumnInfo]]; - } - else if([subcolumnInfo isKindOfClass:[TSColumn class]]) - { - [tmpColumns addObject:subcolumnInfo]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - _subcolumns = tmpColumns; - } - } - return self; -} - -@end - -/**************************************************************************************************************************************/ - -@implementation TSRow - -+ (id)rowWithCells:(NSArray *)cells -{ - return [[TSRow alloc] initWithCells:cells]; -} - -+ (id)rowWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows -{ - return [[TSRow alloc] initWithCells:cells andSubrows:subrows]; -} - -+ (id)rowWithDictionary:(NSDictionary *)info -{ - return [[TSRow alloc] initWithDictionary:info]; -} - -- (id)initWithCells:(NSArray *)cells -{ - return [self initWithCells:cells andSubrows:nil]; -} - -- (id)initWithCells:(NSArray *)cells andSubrows:(NSArray *)subrows -{ - if(self = [super init]) - { - if(cells) - { - NSMutableArray *tmpCells = [[NSMutableArray alloc] initWithCapacity:cells.count]; - for(id cell in cells) - { - if([cell isKindOfClass:[TSCell class]]) - { - [tmpCells addObject:cell]; - } - else - { - [tmpCells addObject:[[TSCell alloc] initWithValue:cell]]; - } - } - _cells = tmpCells; - } - - if(subrows) - { - NSMutableArray *tmpRows = [[NSMutableArray alloc] initWithCapacity:subrows.count]; - for(id row in subrows) - { - if([row isKindOfClass:[TSRow class]]) - { - [tmpRows addObject:row]; - } - else if([row isKindOfClass:[NSArray class]]) - { - [tmpRows addObject:[[TSRow alloc] initWithCells:row]]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - _subrows = tmpRows; - } - } - return self; -} - -- (id)initWithDictionary:(NSDictionary *)info -{ - if(self = [super init]) - { - NSArray *cells = info[@"cells"]; - if(cells) - { - NSMutableArray *tmpCells = [[NSMutableArray alloc] initWithCapacity:cells.count]; - for(id cellInfo in cells) - { - if([cellInfo isKindOfClass:[NSDictionary class]]) - { - [tmpCells addObject:[[TSCell alloc] initWithDictionary:cellInfo]]; - } - else if([cellInfo isKindOfClass:[TSCell class]]) - { - [tmpCells addObject:cellInfo]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - _cells = tmpCells; - } - - NSArray *subrows = info[@"subrows"]; - if(subrows) - { - NSMutableArray *tmpRows = [[NSMutableArray alloc] initWithCapacity:subrows.count]; - for(id rowInfo in subrows) - { - if([rowInfo isKindOfClass:[NSDictionary class]]) - { - [tmpRows addObject:[[TSRow alloc] initWithDictionary:rowInfo]]; - } - else if([rowInfo isKindOfClass:[TSRow class]]) - { - [tmpRows addObject:rowInfo]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - _subrows = tmpRows; - } - } - return self; -} - -@end - -/**************************************************************************************************************************************/ - -@implementation TSCell - -+ (id)cellWithValue:(NSObject *)value -{ - return [[TSCell alloc] initWithValue:value]; -} - -+ (id)cellWithDictionary:(NSDictionary *)info -{ - return [[TSCell alloc] initWithDictionary:info]; -} - -- (id)initWithValue:(NSObject *)value -{ - if(self = [super init]) - { - _textAlignment = NSTextAlignmentCenter; - _value = value; - } - return self; -} - -- (id)initWithDictionary:(NSDictionary *)info -{ - if(self = [super init]) - { - _value = info[@"value"]; - _details = info[@"details"]; - - id colorVal = info[@"textColor"]; - if([colorVal isKindOfClass:[UIColor class]]) - _textColor = colorVal; - else if([colorVal isKindOfClass:[NSString class]]) - _textColor = [TSUtils colorWithHexString:colorVal]; - - colorVal = info[@"detailsColor"]; - if([colorVal isKindOfClass:[UIColor class]]) - _detailsColor = colorVal; - else if([colorVal isKindOfClass:[NSString class]]) - _detailsColor = [TSUtils colorWithHexString:colorVal]; - - id iconVal = info[@"icon"]; - if([iconVal isKindOfClass:[UIImage class]]) - _icon = iconVal; - else if([iconVal isKindOfClass:[NSString class]]) - _icon = [UIImage imageNamed:iconVal]; - - _textAlignment = NSTextAlignmentCenter; - NSString *textAligmentStr = info[@"textAlignment"]; - if(textAligmentStr) - _textAlignment = [textAligmentStr integerValue]; - } - return self; -} - -@end - -/**************************************************************************************************************************************/ - -@interface TSTableViewModel () -{ - NSMutableDictionary *_cachedHeaderSectionBackgroundImages; - NSMutableDictionary *_cachedCellBackgroundImages; - UIImage *_cachedGeneralBackgroundImage; - UIImage *_cachedExpandSectionBackgroundImage; - UIImage *_cachedExpandItemNormalBackgroundImage; - UIImage *_cachedExpandItemSelectedBackgroundImage; -} - -@end - -@implementation TSTableViewModel - -- (id)initWithTableView:(TSTableView *)tableView andStyle:(TSTableViewStyle)style -{ - if(self = [super init]) - { - _tableView = tableView; - _tableView.dataSource = self; - _tableStyle = style; - _heightForRow = DEF_ROW_HEIGHT; - _widthForExpandItem = DEF_EXPAND_ITEM_WIDTH; - - if(_tableStyle == kTSTableViewStyleLight) - { - _tableView.lineNumbersColor = [UIColor blackColor]; - _tableView.backgroundColor = [UIColor grayColor]; - } - else - { - _tableView.lineNumbersColor = [UIColor lightGrayColor]; - _tableView.backgroundColor = [UIColor colorWithWhite:0.12 alpha:1]; - } - - _tableView.headerBackgroundImage = [self generalBackgroundImage]; - _tableView.expandPanelBackgroundImage = [self generalBackgroundImage]; - _tableView.topLeftCornerBackgroundImage = [self generalBackgroundImage]; - _tableView.expandItemNormalBackgroundImage = [self expandItemNormalBackgroundImage]; - _tableView.expandItemSelectedBackgroundImage = [self expandItemSelectedBackgroundImage]; - _tableView.expandSectionBackgroundImage = [self expandSectionBackgroundImage]; - - _rows = [[NSMutableArray alloc] init]; - _columns = [[NSMutableArray alloc] init]; - _bottomEndColumns = [[NSMutableArray alloc] init]; - _cachedHeaderSectionBackgroundImages = [[NSMutableDictionary alloc] init]; - _cachedCellBackgroundImages = [[NSMutableDictionary alloc] init]; - } - return self; -} - -- (void)setColumns:(NSArray *)columns andRows:(NSArray *)rows -{ - VerboseLog(); - [_columns removeAllObjects]; - [_bottomEndColumns removeAllObjects]; - [_rows removeAllObjects]; - - for(id columnInfo in columns) - { - if([columnInfo isKindOfClass:[TSColumn class]]) - { - [_columns addObject:columnInfo]; - } - else if([columnInfo isKindOfClass:[NSString class]]) - { - [_columns addObject:[[TSColumn alloc] initWithTitle:columnInfo]]; - } - else if([columnInfo isKindOfClass:[NSDictionary class]]) - { - [_columns addObject:[TSColumn columnWithDictionary:columnInfo]]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - [self addLeafColumnsFrom:[_columns lastObject]]; - } - - for(id rowInfo in rows) - { - if([rowInfo isKindOfClass:[TSRow class]]) - { - [_rows addObject:rowInfo]; - } - else if([rowInfo isKindOfClass:[NSArray class]]) - { - [_rows addObject:[[TSRow alloc] initWithCells:rowInfo]]; - } - else if([rowInfo isKindOfClass:[NSDictionary class]]) - { - [_rows addObject:[TSRow rowWithDictionary:rowInfo]]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - [_tableView reloadData]; -} - -- (void)addLeafColumnsFrom:(TSColumn *)parentColumn -{ - if(parentColumn.subcolumns.count == 0) - { - [_bottomEndColumns addObject:parentColumn]; - } - else - { - for(TSColumn *column in parentColumn.subcolumns) - { - [self addLeafColumnsFrom:column]; - } - } -} - -- (void)setRows:(NSArray *)rows -{ - VerboseLog(); - [_rows removeAllObjects]; - - for(id rowInfo in rows) - { - if([rowInfo isKindOfClass:[TSRow class]]) - { - [_rows addObject:rowInfo]; - } - else if([rowInfo isKindOfClass:[NSArray class]]) - { - [_rows addObject:[[TSRow alloc] initWithCells:rowInfo]]; - } - else if([rowInfo isKindOfClass:[NSDictionary class]]) - { - [_rows addObject:[TSRow rowWithDictionary:rowInfo]]; - } - else - { - NSAssert(FALSE, @"Type is not supported"); - } - } - [_tableView reloadRowsData]; -} - -- (TSRow *)rowAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - TSRow *row; - NSArray *rows = _rows; - for(int i = 0; i < indexPath.length; ++i) - { - NSInteger index = [indexPath indexAtPosition:i]; - row = rows[index]; - rows = row.subrows; - } - return row; -} - -- (TSColumn *)columnAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - TSColumn *column; - NSArray *columns = _columns; - for(int i = 0; i < indexPath.length; ++i) - { - NSInteger index = [indexPath indexAtPosition:i]; - column = columns[index]; - columns = column.subcolumns; - } - return column; -} - -- (TSCell *)cellAtRowPath:(NSIndexPath *)rowPath atIndex:(NSInteger)index -{ - VerboseLog(); - TSRow *row = [self rowAtPath:rowPath]; - TSCell *cell = row.cells[index]; - return cell; -} - -- (TSColumn *)columnAtIndex:(NSInteger)index -{ - VerboseLog(@"index = %d",index); - - return [_bottomEndColumns objectAtIndex:index]; -} - -// Find specified column recursevly in TSColumn hierarchy -- (TSColumn *)findColumnAtIndex:(NSInteger *)index inColumns:(NSArray *)columns -{ - TSColumn *found; - for (int i = 0; i < columns.count; ++i) - { - TSColumn *column = columns[i]; - if(column.subcolumns.count == 0) - { - if(*index == 0) - return column; - --(*index); - } - else - { - found = [self findColumnAtIndex:index inColumns:column.subcolumns]; - if(found) break; - } - } - return found; -} - -#pragma mark - TSTableViewDataSource - -- (NSInteger)numberOfColumns -{ - VerboseLog(); - return [self calcNumberOfColumns:_columns]; -} - -- (NSInteger)calcNumberOfColumns:(NSArray *)columns -{ - VerboseLog(); - NSInteger columnsCount = columns.count; - for(TSColumn *column in columns) - { - if(column.subcolumns.count) - { - columnsCount += [self calcNumberOfColumns:column.subcolumns] - 1; - } - } - return columnsCount; -} - -- (NSInteger)numberOfRows -{ - VerboseLog(); - return [self calcNumberOfRows:_rows]; -} - -- (NSInteger)calcNumberOfRows:(NSArray *)rows -{ - VerboseLog(); - NSInteger rowsCount = rows.count; - for(TSRow *row in rows) - { - rowsCount += [self calcNumberOfRows:row.subrows]; - } - return rowsCount; -} - -- (NSInteger)numberOfColumnsAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(@"%@", indexPath); - if(indexPath == nil) - return _columns.count; - TSColumn *column = [self columnAtPath:indexPath]; - return column.subcolumns.count; -} - -- (NSInteger)numberOfRowsAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - if(indexPath == nil) - return _rows.count; - TSRow *row = [self rowAtPath:indexPath]; - return row.subrows.count; -} - -- (CGFloat)heightForRowAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - return _heightForRow; -} - -- (CGFloat)heightForHeaderSectionAtPath:(NSIndexPath *)columnPath -{ - VerboseLog(); - TSColumn *columnInfo = [self columnAtPath:columnPath]; - return columnInfo.headerHeight; -} - -- (CGFloat)defaultWidthForColumnAtIndex:(NSInteger)index -{ - TSColumn *columnInfo = [self columnAtIndex:index]; - return columnInfo.defWidth; -} - -- (CGFloat)minimalWidthForColumnAtIndex:(NSInteger)index -{ - TSColumn *columnInfo = [self columnAtIndex:index]; - return columnInfo.minWidth; -} - -- (CGFloat)maximalWidthForColumnAtIndex:(NSInteger)index -{ - TSColumn *columnInfo = [self columnAtIndex:index]; - return columnInfo.maxWidth; -} - -- (CGFloat)widthForExpandItem -{ - VerboseLog(); - return _widthForExpandItem; -} - -- (TSTableViewCell *)tableView:(TSTableView *)tableView cellViewForRowAtPath:(NSIndexPath *)indexPath cellIndex:(NSInteger)index -{ - VerboseLog(); - NSString * const kReuseCellId = @"TSTableViewCell"; - TSCell *cellInfo = [self cellAtRowPath:indexPath atIndex:index]; - TSTableViewCell *cell = [tableView dequeueReusableCellViewWithIdentifier:kReuseCellId]; - if(!cell) - cell = [[TSTableViewCell alloc] initWithReuseIdentifier:kReuseCellId]; - - TSColumn *columnInfo = [self columnAtIndex:index]; - if(columnInfo.titleColor) - { - cell.textLabel.textColor = columnInfo.titleColor; - } - else - { - if(_tableStyle == kTSTableViewStyleDark) - cell.textLabel.textColor = [UIColor grayColor]; - else - cell.textLabel.textColor = [UIColor darkGrayColor]; - } - - if(cellInfo.value) - { - cell.textLabel.text = [cellInfo.value description]; - cell.textLabel.textAlignment = cellInfo.textAlignment; - if(cellInfo.textColor) - cell.textLabel.textColor = cellInfo.textColor; - } - if(cellInfo.details) - { - cell.detailsLabel.text = cellInfo.details; - cell.detailsLabel.textAlignment = cellInfo.textAlignment; - if(cellInfo.detailsColor) - cell.detailsLabel.textColor = cellInfo.detailsColor; - } - if(cellInfo.icon) - cell.iconView.image = cellInfo.icon; - - // Color values and proportions below just came up from my head, there is no special logic for this... it just looks fine, that's all - if(columnInfo.color) - { - CGFloat color = 0.9f + 0.1f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); - CGColorRef colorRef = columnInfo.color.CGColor; - const float *rgb = CGColorGetComponents(colorRef); - cell.backgroundImageView.image = [self cellBackgroundImageWithTintColor:[UIColor colorWithRed:color * rgb[0] green:color * rgb[1] blue:color * rgb[2] alpha:1]]; - } - else - { - CGFloat color; - if(_tableStyle == kTSTableViewStyleDark) - color = 0.16f + 0.04f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); - else - color = 0.9f + 0.1f * (1 - (indexPath.length - 1)/(float)tableView.maxNestingLevel); - cell.backgroundImageView.image = [self cellBackgroundImageWithTintColor:[UIColor colorWithWhite:color alpha:1]]; - } - return cell; -} - -- (TSTableViewHeaderSectionView *)tableView:(TSTableView *)tableView headerSectionViewForColumnAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - TSColumn *column = [self columnAtPath:indexPath]; - TSTableViewHeaderSectionView *section = [[TSTableViewHeaderSectionView alloc] init]; - - if(_tableStyle == kTSTableViewStyleDark) - { - section.textLabel.layer.shadowColor = [UIColor blackColor].CGColor; - section.textLabel.textColor = [UIColor grayColor]; - } - else - { - section.textLabel.textColor = [UIColor darkGrayColor]; - } - section.backgroundImageView.image = [self headerSectionBackgroundImageWithTintColor:column.color]; - - if(column.title) - { - section.textLabel.text = column.title; - section.textLabel.textAlignment = column.textAlignment; - } - if(column.subtitle) - { - section.detailsLabel.text = column.subtitle; - section.detailsLabel.textAlignment = column.textAlignment; - } - if(column.icon) - section.iconView.image = column.icon; - if(column.titleColor) - section.textLabel.textColor = column.titleColor; - if(column.subtitleColor) - section.detailsLabel.textColor = column.subtitleColor; - if(column.titleFontSize) - section.textLabel.font = [UIFont boldSystemFontOfSize:column.titleFontSize]; - if(column.subtitleFontSize) - section.detailsLabel.font = [UIFont boldSystemFontOfSize:column.subtitleFontSize]; - - return section; -} - -#pragma mark - Modify content - -- (void)insertRow:(TSRow *)rowInfo atPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - TSRow *row; - NSMutableArray *rows = _rows; - for(int i = 0; i < indexPath.length - 1; ++i) - { - NSInteger index = [indexPath indexAtPosition:i]; - row = rows[index]; - rows = row.subrows; - } - NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; - [rows insertObject:rowInfo atIndex:lastIndex]; - [_tableView insertRowAtPath:indexPath animated:YES]; -} - -- (void)removeRowAtPath:(NSIndexPath *)indexPath -{ - VerboseLog(); - TSRow *row; - NSMutableArray *rows = _rows; - for(int i = 0; i < indexPath.length - 1; ++i) - { - NSInteger index = [indexPath indexAtPosition:i]; - row = rows[index]; - rows = row.subrows; - } - NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; - [rows removeObjectAtIndex:lastIndex]; - [_tableView removeRowAtPath:indexPath animated:YES]; -} - -- (void)replcaceRowAtPath:(NSIndexPath *)indexPath withRow:(TSRow *)rowInfo -{ - VerboseLog(); - TSRow *row; - NSMutableArray *rows = _rows; - for(int i = 0; i < indexPath.length - 1; ++i) - { - NSInteger index = [indexPath indexAtPosition:i]; - row = rows[index]; - rows = row.subrows; - } - NSInteger lastIndex = [indexPath indexAtPosition:indexPath.length - 1]; - [rows replaceObjectAtIndex:lastIndex withObject:rowInfo]; - [_tableView updateRowAtPath:indexPath]; -} - -#pragma mark - Create background images - -- (NSString *)keyForColor:(UIColor *)color -{ - if(!color) return @""; - const CGFloat *rgba = CGColorGetComponents(color.CGColor); - return [NSString stringWithFormat:@"%d%d%d%d", (char)(rgba[0] * 255), (char)(rgba[1] * 255), (char)(rgba[2] * 255), (char)(rgba[3] * 255)]; -} - -- (UIImage *)cellBackgroundImageWithTintColor:(UIColor *)color -{ - NSString *key = [self keyForColor:color]; - UIImage *image = _cachedCellBackgroundImages[key]; - if(!image) - { - if(_tableStyle == kTSTableViewStyleDark) - image = [self darkCellBackgroundImageWithTintColor:color]; - else - image = [self lightCellBackgroundImageWithTintColor:color]; - _cachedCellBackgroundImages[key] = image; - } - return image; -} - -- (UIImage *)headerSectionBackgroundImageWithTintColor:(UIColor *)color -{ - NSString *key = [self keyForColor:color]; - UIImage *image = _cachedHeaderSectionBackgroundImages[key]; - if(!image) - { - if(_tableStyle == kTSTableViewStyleDark) - image = [self darkHeaderSectionBackgroundImageWithTintColor:color]; - else - image = [self lightHeaderSectionBackgroundImageWithTintColor:color]; - _cachedHeaderSectionBackgroundImages[key] = image; - } - return image; -} - -- (UIImage *)expandSectionBackgroundImage -{ - if(!_cachedExpandSectionBackgroundImage) - { - if(_tableStyle == kTSTableViewStyleDark) - _cachedExpandSectionBackgroundImage = [self darkExpandSectionBackgroundImage]; - else - _cachedExpandSectionBackgroundImage = [self lightExpandSectionBackgroundImage]; - } - return _cachedExpandSectionBackgroundImage; -} - -- (UIImage *)expandItemNormalBackgroundImage -{ - if(!_cachedExpandItemNormalBackgroundImage) - { - if(_tableStyle == kTSTableViewStyleDark) - _cachedExpandItemNormalBackgroundImage = [self darkExpandItemNormalBackgroundImage]; - else - _cachedExpandItemNormalBackgroundImage = [self lightExpandItemNormalBackgroundImage]; - } - return _cachedExpandItemNormalBackgroundImage; -} - -- (UIImage *)expandItemSelectedBackgroundImage -{ - if(!_cachedExpandItemSelectedBackgroundImage) - { - if(_tableStyle == kTSTableViewStyleDark) - _cachedExpandItemSelectedBackgroundImage = [self darkExpandItemSelectedBackgroundImage]; - else - _cachedExpandItemSelectedBackgroundImage = [self lightExpandItemSelectedBackgroundImage]; - } - return _cachedExpandItemSelectedBackgroundImage; -} - -- (UIImage *)generalBackgroundImage -{ - if(!_cachedGeneralBackgroundImage) - { - if(_tableStyle == kTSTableViewStyleDark) - _cachedGeneralBackgroundImage = [self darkGeneralBackgroundImage]; - else - _cachedGeneralBackgroundImage = [self lightGeneralBackgroundImage]; - } - return _cachedGeneralBackgroundImage; -} - -#pragma mark - Create background images for Light style - -- (UIImage *)lightCellBackgroundImageWithTintColor:(UIColor *)color -{ - UIColor *topColor = (color ? color : [UIColor whiteColor]); - UIColor *bottomColor = (color ? color : [UIColor whiteColor]); - UIColor *topBorderColor = [UIColor whiteColor]; - UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor whiteColor]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - -- (UIImage *)lightHeaderSectionBackgroundImageWithTintColor:(UIColor *)color -{ - UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; - UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.9f alpha:1.0f]); - UIColor *topBorderColor = [UIColor whiteColor]; - UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor whiteColor]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; - - CGFloat lineWidth = 8; - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - lineWidth/2, 0) - endPoint:CGPointMake(rect.size.width - lineWidth/2, rect.size.height - 0.5f) - color:lineColor.CGColor - lineWidth:lineWidth]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - -- (UIImage *)lightExpandSectionBackgroundImage -{ - UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; - UIColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; - UIColor *topBorderColor = [UIColor whiteColor]; - UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor whiteColor]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; - - CGFloat lineWidth = 8; - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(lineWidth/2, 0) - endPoint:CGPointMake(lineWidth/2, rect.size.height - 0.5f) - color:lineColor.CGColor - lineWidth:lineWidth]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - - -- (UIImage *)lightExpandItemNormalBackgroundImage -{ - CGFloat expandItemWidth = [self widthForExpandItem]; - CGFloat rowHeight = [self heightForRow]; - CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGFloat lineWithd = 8; - NSArray *points = @[ - [NSValue valueWithCGPoint:CGPointMake(lineWithd + 1, CGRectGetMidY(rect) - lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth - 5, CGRectGetMidY(rect) - lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect))], - - [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth - 5, CGRectGetMidY(rect) + lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd + 1, CGRectGetMidY(rect) + lineWithd/2)] - ]; - - [TSUtils drawPolygonInContext:context points:points - fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor - strokeColor:[UIColor clearColor].CGColor - strokeSize:0]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return image; -} - -- (UIImage *)lightExpandItemSelectedBackgroundImage -{ - CGFloat expandItemWidth = [self widthForExpandItem]; - CGFloat rowHeight = [self heightForRow]; - CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGFloat lineWithd = 8; - - NSArray *points = @[ - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd/2, CGRectGetMaxY(rect) - 2)], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth - lineWithd/2, CGRectGetMaxY(rect) - 14)], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + 3 * lineWithd/2, CGRectGetMaxY(rect) - 14)] - ]; - - [TSUtils drawPolygonInContext:context points:points - fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor - strokeColor:[UIColor clearColor].CGColor - strokeSize:0]; - - NSArray *points1 = @[ - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect))], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect) - 6)], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd/2, CGRectGetMaxY(rect))], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect) - 6)], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect))] - ]; - - [TSUtils drawPolygonInContext:context points:points1 - fillColor:[UIColor colorWithWhite:0 alpha:0.1].CGColor - strokeColor:[UIColor clearColor].CGColor - strokeSize:0]; - - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - -- (UIImage *)lightGeneralBackgroundImage -{ - UIColor *topColor = [UIColor colorWithWhite:0.95f alpha:1.0f]; - UIColor *bottomColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; - UIColor *topBorderColor = [UIColor whiteColor]; - UIColor *bottomBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor whiteColor]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.7f alpha:1.0f]; - - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - -#pragma mark - Create background images for Dark Style - -- (UIImage *)darkCellBackgroundImageWithTintColor:(UIColor *)color -{ - UIColor *topColor = (color ? color : [UIColor colorWithWhite:0.2f alpha:1.0f]); - UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.15f alpha:1.0f]); - UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; - - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - -- (UIImage *)darkHeaderSectionBackgroundImageWithTintColor:(UIColor *)color -{ - UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; - UIColor *bottomColor = (color ? color : [UIColor colorWithWhite:0.15f alpha:1.0f]); - UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *lineColor = [UIColor colorWithWhite:0.0f alpha:0.1f]; - - CGFloat lineWidth = 8; - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - lineWidth/2, 0) - endPoint:CGPointMake(rect.size.width - lineWidth/2, rect.size.height - 0.5f) - color:lineColor.CGColor - lineWidth:lineWidth]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/4]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(2, rect.size.width/2, 2, rect.size.width/2) resizingMode:UIImageResizingModeStretch]; -} - -- (UIImage *)darkExpandSectionBackgroundImage -{ - UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; - UIColor *bottomColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; - UIColor *topBorderColor = [UIColor colorWithWhite:0.3f alpha:1.0f]; - UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *lineColor = [UIColor colorWithWhite:0 alpha:0.15f]; - - CGFloat lineWidth = 8; - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(lineWidth/2, 0) - endPoint:CGPointMake(lineWidth/2, rect.size.height - 0.5f) - color:lineColor.CGColor - lineWidth:lineWidth]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - - -- (UIImage *)darkExpandItemNormalBackgroundImage -{ - CGFloat expandItemWidth = [self widthForExpandItem]; - CGFloat rowHeight = [self heightForRow]; - CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGFloat lineWithd = 8; - NSArray *points = @[ - [NSValue valueWithCGPoint:CGPointMake(lineWithd , CGRectGetMidY(rect) - lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect) - lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd + expandItemWidth, CGRectGetMidY(rect) + lineWithd/2)], - [NSValue valueWithCGPoint:CGPointMake(lineWithd , CGRectGetMidY(rect) + lineWithd/2)] - ]; - - CGMutablePathRef path = CGPathCreateMutable(); - for(int i = 0; i < points.count; ++i) - { - NSValue *pointVal = points[i]; - CGPoint point = [pointVal CGPointValue]; - if(i == 0) - CGPathMoveToPoint(path, NULL, point.x, point.y); - else - CGPathAddLineToPoint(path, NULL, point.x, point.y); - } - CGFloat radius = 8; - CGPathAddEllipseInRect(path, NULL, CGRectMake(expandItemWidth + lineWithd/2 - radius, CGRectGetMidY(rect) - radius, 2*radius, 2*radius)); - - CGPathCloseSubpath(path); - - - CGContextSaveGState(context); - - CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:0.15].CGColor); - CGContextAddPath(context, path); - CGContextFillPath(context); - - CGContextSetStrokeColorWithColor(context, [UIColor colorWithWhite:1 alpha:0.1].CGColor); - CGFloat innerRadius = 3.5f; - CGContextAddEllipseInRect(context, CGRectMake(expandItemWidth + lineWithd/2 - innerRadius, CGRectGetMidY(rect) - innerRadius, 2*innerRadius, 2*innerRadius)); - CGContextStrokePath(context); - CGContextRestoreGState(context); - - CGPathRelease(path); - - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - -- (UIImage *)darkExpandItemSelectedBackgroundImage -{ - CGFloat expandItemWidth = [self widthForExpandItem]; - CGFloat rowHeight = [self heightForRow]; - CGRect rect = CGRectMake(0.0f, 0.0f, 2 * expandItemWidth, rowHeight); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - CGFloat lineWithd = 8; - NSArray *points = @[ - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMaxY(rect))], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth, CGRectGetMidY(rect))], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMidY(rect))], - [NSValue valueWithCGPoint:CGPointMake(expandItemWidth + lineWithd, CGRectGetMaxY(rect))] - ]; - - CGMutablePathRef path = CGPathCreateMutable(); - for(int i = 0; i < points.count; ++i) - { - NSValue *pointVal = points[i]; - CGPoint point = [pointVal CGPointValue]; - if(i == 0) - CGPathMoveToPoint(path, NULL, point.x, point.y); - else - CGPathAddLineToPoint(path, NULL, point.x, point.y); - } - CGFloat radius = 8; - CGPathAddEllipseInRect(path, NULL, CGRectMake(expandItemWidth + lineWithd/2 - radius, CGRectGetMidY(rect) - radius, 2*radius, 2*radius)); - - CGPathCloseSubpath(path); - - - CGContextSaveGState(context); - - CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0 alpha:0.15].CGColor); - CGContextAddPath(context, path); - CGContextFillPath(context); - - CGContextSetFillColorWithColor(context, [UIColor colorWithWhite:0.185 alpha:1].CGColor); - CGFloat innerRadius = 3.5f; - CGContextAddEllipseInRect(context, CGRectMake(expandItemWidth + lineWithd/2 - innerRadius, CGRectGetMidY(rect) - innerRadius, 2*innerRadius, 2*innerRadius)); - CGContextFillPath(context); - CGContextRestoreGState(context); - - CGPathRelease(path); - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return image; -} - -- (UIImage *)darkGeneralBackgroundImage -{ - UIColor *topColor = [UIColor colorWithWhite:0.2f alpha:1.0f]; - UIColor *bottomColor = [UIColor colorWithWhite:0.15f alpha:1.0f]; - UIColor *topBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *bottomBorderColor =[UIColor colorWithWhite:0.05f alpha:1.0f]; - UIColor *leftBorderColor = [UIColor colorWithWhite:0.4f alpha:1.0f]; - UIColor *rightBorderColor = [UIColor colorWithWhite:0.05f alpha:1.0f]; - - CGRect rect = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); - UIGraphicsBeginImageContextWithOptions(rect.size, NO, [[UIScreen mainScreen] scale]); - CGContextRef context = UIGraphicsGetCurrentContext(); - - [TSUtils drawLinearGradientInContext:context - rect:rect - startColor:topColor.CGColor - endColor:bottomColor.CGColor]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, 0) - color:topBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, rect.size.height - 0.5f) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:bottomBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(rect.size.width - 0.5f, 0) - endPoint:CGPointMake(rect.size.width - 0.5f, rect.size.height - 0.5f) - color:rightBorderColor.CGColor - lineWidth:0.5]; - [TSUtils drawLineInContext:context - startPoint:CGPointMake(0, 0) - endPoint:CGPointMake(0, rect.size.height - 0.5f) - color:leftBorderColor.CGColor - lineWidth:0.5]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - - return [image stretchableImageWithLeftCapWidth:rect.size.width/2 topCapHeight:rect.size.height/2]; - //return [image resizableImageWithCapInsets:UIEdgeInsetsMake(rect.size.height/2, rect.size.width/2, rect.size.height/2, rect.size.width/2)]; -} - - -@end diff --git a/TSUIKit.xcodeproj/project.pbxproj b/TSUIKit.xcodeproj/project.pbxproj index 1905ab2..66d8ba3 100644 --- a/TSUIKit.xcodeproj/project.pbxproj +++ b/TSUIKit.xcodeproj/project.pbxproj @@ -94,11 +94,6 @@ F6141F3D17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEA17C6A64C003455EB /* TSTableViewHeaderSectionView.m */; }; F6141F3E17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEA17C6A64C003455EB /* TSTableViewHeaderSectionView.m */; }; F6141F3F17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEA17C6A64C003455EB /* TSTableViewHeaderSectionView.m */; }; - F6141F4017C6A64C003455EB /* TSTableViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEC17C6A64C003455EB /* TSTableViewModel.m */; }; - F6141F4117C6A64C003455EB /* TSTableViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEC17C6A64C003455EB /* TSTableViewModel.m */; }; - F6141F4217C6A64C003455EB /* TSTableViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEC17C6A64C003455EB /* TSTableViewModel.m */; }; - F6141F4317C6A64C003455EB /* TSTableViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEC17C6A64C003455EB /* TSTableViewModel.m */; }; - F6141F4417C6A64C003455EB /* TSTableViewModel.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEC17C6A64C003455EB /* TSTableViewModel.m */; }; F6141F4517C6A64C003455EB /* TSTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEF17C6A64C003455EB /* TSTabView.m */; }; F6141F4617C6A64C003455EB /* TSTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEF17C6A64C003455EB /* TSTabView.m */; }; F6141F4717C6A64C003455EB /* TSTabView.m in Sources */ = {isa = PBXBuildFile; fileRef = F6141EEF17C6A64C003455EB /* TSTabView.m */; }; @@ -507,8 +502,6 @@ F6141EE817C6A64C003455EB /* TSTableViewDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSTableViewDelegate.h; sourceTree = ""; }; F6141EE917C6A64C003455EB /* TSTableViewHeaderSectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSTableViewHeaderSectionView.h; sourceTree = ""; }; F6141EEA17C6A64C003455EB /* TSTableViewHeaderSectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSTableViewHeaderSectionView.m; sourceTree = ""; }; - F6141EEB17C6A64C003455EB /* TSTableViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSTableViewModel.h; sourceTree = ""; }; - F6141EEC17C6A64C003455EB /* TSTableViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSTableViewModel.m; sourceTree = ""; }; F6141EEE17C6A64C003455EB /* TSTabView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSTabView.h; sourceTree = ""; }; F6141EEF17C6A64C003455EB /* TSTabView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSTabView.m; sourceTree = ""; }; F6141EF017C6A64C003455EB /* TSTabViewDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSTabViewDataSource.h; sourceTree = ""; }; @@ -785,8 +778,6 @@ F6141EE817C6A64C003455EB /* TSTableViewDelegate.h */, F6141EE917C6A64C003455EB /* TSTableViewHeaderSectionView.h */, F6141EEA17C6A64C003455EB /* TSTableViewHeaderSectionView.m */, - F6141EEB17C6A64C003455EB /* TSTableViewModel.h */, - F6141EEC17C6A64C003455EB /* TSTableViewModel.m */, ); path = TSTableView; sourceTree = ""; @@ -1653,7 +1644,6 @@ F6141F3317C6A64C003455EB /* TSTableView.m in Sources */, F6141F3817C6A64C003455EB /* TSTableViewCell.m in Sources */, F6141F3D17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */, - F6141F4217C6A64C003455EB /* TSTableViewModel.m in Sources */, F6141F4717C6A64C003455EB /* TSTabView.m in Sources */, F6141F4C17C6A64C003455EB /* TSTabViewModel.m in Sources */, F6141F5117C6A64C003455EB /* TSTabViewWithDropDownPanel.m in Sources */, @@ -1687,7 +1677,6 @@ F6141F3117C6A64C003455EB /* TSTableView.m in Sources */, F6141F3617C6A64C003455EB /* TSTableViewCell.m in Sources */, F6141F3B17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */, - F6141F4017C6A64C003455EB /* TSTableViewModel.m in Sources */, F6141F4517C6A64C003455EB /* TSTabView.m in Sources */, F6141F4A17C6A64C003455EB /* TSTabViewModel.m in Sources */, F6141F4F17C6A64C003455EB /* TSTabViewWithDropDownPanel.m in Sources */, @@ -1717,7 +1706,6 @@ F6141F3217C6A64C003455EB /* TSTableView.m in Sources */, F6141F3717C6A64C003455EB /* TSTableViewCell.m in Sources */, F6141F3C17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */, - F6141F4117C6A64C003455EB /* TSTableViewModel.m in Sources */, F6141F4617C6A64C003455EB /* TSTabView.m in Sources */, F6141F4B17C6A64C003455EB /* TSTabViewModel.m in Sources */, F6141F5017C6A64C003455EB /* TSTabViewWithDropDownPanel.m in Sources */, @@ -1745,7 +1733,6 @@ F6141F3517C6A64C003455EB /* TSTableView.m in Sources */, F6141F3A17C6A64C003455EB /* TSTableViewCell.m in Sources */, F6141F3F17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */, - F6141F4417C6A64C003455EB /* TSTableViewModel.m in Sources */, F6141F4917C6A64C003455EB /* TSTabView.m in Sources */, F6141F4E17C6A64C003455EB /* TSTabViewModel.m in Sources */, F6141F5317C6A64C003455EB /* TSTabViewWithDropDownPanel.m in Sources */, @@ -1774,7 +1761,6 @@ F6141F3417C6A64C003455EB /* TSTableView.m in Sources */, F6141F3917C6A64C003455EB /* TSTableViewCell.m in Sources */, F6141F3E17C6A64C003455EB /* TSTableViewHeaderSectionView.m in Sources */, - F6141F4317C6A64C003455EB /* TSTableViewModel.m in Sources */, F6141F4817C6A64C003455EB /* TSTabView.m in Sources */, F6141F4D17C6A64C003455EB /* TSTabViewModel.m in Sources */, F6141F5217C6A64C003455EB /* TSTabViewWithDropDownPanel.m in Sources */, @@ -2120,6 +2106,7 @@ F63D2F1717CE48F900515A24 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; F680D29C1774B9C3005ACD94 /* Build configuration list for PBXNativeTarget "TabViewTest" */ = { isa = XCConfigurationList; diff --git a/TableView/TSTableViewController+TestDataDefinition.m b/TableView/TSTableViewController+TestDataDefinition.m index 58f02c4..e168345 100644 --- a/TableView/TSTableViewController+TestDataDefinition.m +++ b/TableView/TSTableViewController+TestDataDefinition.m @@ -7,7 +7,7 @@ // #import "TSTableViewController+TestDataDefinition.h" -#import "TSTableViewModel.h" +#import "TSTableView.h" @implementation TSTableViewController (TestDataDefinition) diff --git a/TableView/TSTableViewController.m b/TableView/TSTableViewController.m index eb6eb80..64a4816 100644 --- a/TableView/TSTableViewController.m +++ b/TableView/TSTableViewController.m @@ -7,7 +7,7 @@ // #import "TSTableViewController.h" -#import "TSTableViewModel.h" +#import "TSTableView.h" #import "TSDefines.h" #import "TSTableViewController+TestDataDefinition.h" #import @@ -16,8 +16,8 @@ @interface TSTableViewController () { TSTableView *_tableView1; TSTableView *_tableView2; - TSTableViewModel *_model1; - TSTableViewModel *_model2; +// TSTableViewModel *_model1; +// TSTableViewModel *_model2; NSArray *_tables; NSArray *_dataModels; @@ -40,41 +40,41 @@ - (void)viewDidLoad self.settingsView.layer.shadowOffset = CGSizeMake(2, 4); // Top table - _tableView1 = [[TSTableView alloc] initWithFrame:CGRectMake(20, 80, self.view.frame.size.width - 40, self.view.frame.size.height/2 - 70)]; + _tableView1 = [[TSTableView alloc] initWithFrame:CGRectMake(20, 80, self.view.frame.size.width - 40, self.view.frame.size.height/2 - 70) andStyle:kTSTableViewStyleLight]; _tableView1.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; _tableView1.delegate = self; [self.view addSubview:_tableView1]; - _model1 = [[TSTableViewModel alloc] initWithTableView:_tableView1 andStyle:kTSTableViewStyleDark]; +// _model1 = [[TSTableViewModel alloc] initWithTableView:_tableView1 andStyle:kTSTableViewStyleDark]; // NSArray *columns1 = [self columnsInfo1]; // NSArray *rows1 = [self rowsInfo1]; // [_model1 setColumns:columns1 andRows:rows1]; NSArray *columns1 = [self columnsForFileSystemTree]; NSArray *rows1 = [self rowsForAppDirectory]; - [_model1 setColumns:columns1 andRows:rows1]; + [_tableView1 setColumns:columns1 andRows:rows1]; // Bottom table - _tableView2 = [[TSTableView alloc] initWithFrame:CGRectMake(20, self.view.frame.size.height/2 + 50, self.view.frame.size.width - 40, self.view.frame.size.height/2 - 70)]; - _tableView2.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - _tableView2.delegate = self; +// _tableView2 = [[TSTableView alloc] initWithFrame:CGRectMake(20, self.view.frame.size.height/2 + 50, self.view.frame.size.width - 40, self.view.frame.size.height/2 - 70) andStyle:kTSTableViewStyleDark]; +// _tableView2.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; +// _tableView2.delegate = self; +// +// [self.view addSubview:_tableView2]; - [self.view addSubview:_tableView2]; - - _model2 = [[TSTableViewModel alloc] initWithTableView:_tableView2 andStyle:kTSTableViewStyleLight]; +// _model2 = [[TSTableViewModel alloc] initWithTableView:_tableView2 andStyle:kTSTableViewStyleLight]; // NSArray *columns2 = [self columnsInfo2]; // NSArray *rows2 = [self rowsInfo2]; // [_model2 setColumns:columns2 andRows:rows2]; - NSArray *columns2 = [self columnsForFileSystemTree]; - NSArray *rows2 = [self rowsForAppDirectory]; - [_model2 setColumns:columns2 andRows:rows2]; +// NSArray *columns2 = [self columnsForFileSystemTree]; +// NSArray *rows2 = [self rowsForAppDirectory]; +// [_tableView2 setColumns:columns2 andRows:rows2]; - _dataModels = @[_model1, _model2]; - _tables = @[_tableView1, _tableView2]; +// _dataModels = @[_model1, _model2]; + _tables = @[_tableView1]; // Row examples should correspond to columnsInfo* and rowsInfo* used above // _rowExamples = @[ @@ -82,10 +82,10 @@ - (void)viewDidLoad // [self rowExample2], // ]; - _rowExamples = @[ - [self rowForDummyFile], - [self rowForDummyFile], - ]; +// _rowExamples = @[ +// [self rowForDummyFile], +// [self rowForDummyFile], +// ]; } @@ -102,27 +102,25 @@ - (IBAction)numberOfRowsValueChanged:(UIStepper *)stepper NSInteger val = [stepper value]; if(val > _stepperPreviousValue) { - for(int i = 0; i < _dataModels.count; ++i) + for(int i = 0; i < _tables.count; ++i) { TSTableView *table = _tables[i]; - TSTableViewModel *model = _dataModels[i]; NSIndexPath *rowPath = [table pathToSelectedRow]; if(!rowPath) rowPath = [NSIndexPath indexPathWithIndex:0]; TSRow *row = _rowExamples[i]; - [model insertRow:row atPath:rowPath]; + [table insertRow:row atPath:rowPath]; } } else { - for(int i = 0; i < _dataModels.count; ++i) + for(int i = 0; i < _tables.count; ++i) { TSTableView *table = _tables[i]; - TSTableViewModel *model = _dataModels[i]; NSIndexPath *rowPath = [table pathToSelectedRow]; if(rowPath) - [model removeRowAtPath:rowPath]; + [table removeRowAtPath:rowPath]; } } @@ -159,31 +157,60 @@ - (IBAction)resetSelectionButtonPressed - (void)tableView:(TSTableView *)tableView willSelectRowAtPath:(NSIndexPath *)rowPath selectedCell:(NSInteger)cellIndex animated:(BOOL)animated { VerboseLog(); +// NSLog(@"willSelectRowAtPath"); } - (void)tableView:(TSTableView *)tableView didSelectRowAtPath:(NSIndexPath *)rowPath selectedCell:(NSInteger)cellIndex { VerboseLog(); +// NSLog(@"didSelectRowAtPath"); } - (void)tableView:(TSTableView *)tableView willSelectColumnAtPath:(NSIndexPath *)columnPath animated:(BOOL)animated { VerboseLog(); +// NSLog(@"willSelectColumnAtPath"); } - (void)tableView:(TSTableView *)tableView didSelectColumnAtPath:(NSIndexPath *)columnPath { VerboseLog(); +// NSLog(@"didSelectColumnAtPath"); } - (void)tableView:(TSTableView *)tableView widthDidChangeForColumnAtIndex:(NSInteger)columnIndex { VerboseLog(); +// NSLog(@"widthDidChangeForColumnAtIndex"); } - (void)tableView:(TSTableView *)tableView expandStateDidChange:(BOOL)expand forRowAtPath:(NSIndexPath *)rowPath { VerboseLog(); +// NSLog(@"expandStateDidChange"); +} + +//mark: cell click callback 1 +- (void)tableView:(TSTableView *)tableView tapCellView:(TSTableViewCell*)cell cellValue:(NSString*)value +{ +// NSInteger col = cell.colIndex; +// NSIndexPath *rowPath = cell.rowPath; +// NSString *pathstr = rowPath.description; +// NSString *pre = @"path ="; +// NSString *suff = @"}"; +// NSRange preRange = [pathstr rangeOfString:pre]; +// NSUInteger preIndex = preRange.location + preRange.length; +// NSRange suffRange = [pathstr rangeOfString:suff]; +// NSUInteger suffIndex = suffRange.location; +// NSRange rang = NSMakeRange(preIndex+1, suffIndex-preIndex-1); +// NSString *row = [pathstr substringWithRange:rang]; +// NSLog(@"rowpath = %@ ,col = %d ,value = %@",row,col,value); +} + +//mark: cell click callback 2 +- (void)cellClickWithRowPath:(NSString *)rowPath colIndex:(NSInteger)col cellValue:(NSString *)value +{ + NSLog(@"rowpath = %@ ,col = %d ,value = %@",rowPath,col,value); } #pragma mark - FileSystem @@ -234,6 +261,7 @@ - (NSArray *)rowsForDirectory:(NSURL *)rootUrl options:0//(NSDirectoryEnumerationSkipsHiddenFiles) error:&error]; NSMutableArray *rows = [[NSMutableArray alloc] initWithCapacity:array.count]; + NSInteger r = 11; for(NSURL * url in array) { NSString *localizedName = nil; @@ -289,16 +317,18 @@ - (NSArray *)rowsForDirectory:(NSURL *)rootUrl [url getResourceValue:&modificationDate forKey:NSURLContentModificationDateKey error:NULL]; TSRow *row = [TSRow rowWithDictionary:@{ + @"rowHead" : [NSString stringWithFormat:@"%d",r], @"cells" : @[ cellFilename, @{@"value" : fileSizeStr}, @{@"value" : [dateFormatter stringFromDate:modificationDate]}, @{@"value" : [dateFormatter stringFromDate:creationDate]} - ], - @"subrows" : subrows + ] + ,@"subrows" : subrows }]; [rows addObject:row]; + r++; } return [NSArray arrayWithArray:rows]; } diff --git a/TableView/en.lproj/TSTableViewController.xib b/TableView/en.lproj/TSTableViewController.xib index 4650923..7380175 100644 --- a/TableView/en.lproj/TSTableViewController.xib +++ b/TableView/en.lproj/TSTableViewController.xib @@ -1,124 +1,22 @@ - - - - 1552 - 12E55 - 3084 - 1187.39 - 626.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 2083 - - - IBProxyObject - IBUIView - - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - - {{0, 20}, {320, 548}} - - - 3 - MC4zMzMzMzMzMzMzAA - - NO - - - IBUIScreenMetrics - - YES - - - - - - {320, 568} - {568, 320} - - - IBCocoaTouchFramework - Retina 4 Full Screen - 2 - - IBCocoaTouchFramework - - - - - - - view - - - - 7 - - - - - - 0 - - - - - - -1 - - - File's Owner - - - -2 - - - - - 6 - - - - - - - - TSTableViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - - - 10 - - - 0 - IBCocoaTouchFramework - YES - 3 - YES - 2083 - - + + + + + + + + + + + + + + + + + + + + + +