libs-gui/Source/NSGridView.m
2023-11-20 22:43:49 +01:00

1235 lines
30 KiB
Objective-C

/* Implementation of class NSGridView
Copyright (C) 2020 Free Software Foundation, Inc.
By: Gregory John Casamento
Date: 08-08-2020
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import <Foundation/NSArray.h>
#import "AppKit/NSGridView.h"
#import "GSFastEnumeration.h"
//
// This is, admittedly, a kludge. Some controls were not working
// when placed so close together (the checkbox, in particular).
//
#define MIN_SPACING 5.0
// Private interfaces...
@interface NSGridCell (Private)
- (void) _setOwningRow: (NSGridRow *)r;
- (void) _setOwningColumn: (NSGridColumn *)c;
@end
@interface NSGridView (Private)
- (NSRect) _prototypeFrame;
- (NSArray *) _cellsForRowAtIndex: (NSUInteger)rowIndex;
- (NSArray *) _viewsForRowAtIndex: (NSUInteger)rowIndex;
- (NSArray *) _cellsForColumnAtIndex: (NSUInteger)columnIndex;
- (NSArray *) _viewsForColumnAtIndex: (NSUInteger)columnIndex;
@end
@implementation NSGridView (Private)
- (NSRect) _prototypeFrame
{
NSRect vf = [self frame];
NSRect f = NSMakeRect(0.0, 0.0,
((vf.size.width - (_columnSpacing + MIN_SPACING)) / [self numberOfColumns]),
((vf.size.height - (_rowSpacing + MIN_SPACING)) / [self numberOfRows]));
return f;
}
- (NSArray *) _cellsForRowAtIndex: (NSUInteger)rowIndex
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity: [_columns count]];
NSGridRow *row = [_rows objectAtIndex: rowIndex];
FOR_IN(NSGridCell*, c, _cells)
{
if ([c row] == row)
{
[result addObject: c];
}
}
END_FOR_IN(_cells);
return result;
}
- (NSArray *) _viewsForRowAtIndex: (NSUInteger)rowIndex
{
NSArray *cells = [self _cellsForRowAtIndex: rowIndex];
NSMutableArray *result = [NSMutableArray arrayWithCapacity: [_columns count]];
FOR_IN(NSGridCell*, c, cells)
{
NSView *v = [c contentView];
if (c != nil)
{
[result addObject: v];
}
else
{
[result addObject: [NSGridCell emptyContentView]];
}
}
END_FOR_IN(cells);
return result;
}
- (NSArray *) _cellsForColumnAtIndex: (NSUInteger)columnIndex
{
NSMutableArray *result = [NSMutableArray arrayWithCapacity: [_rows count]];
NSGridColumn *col = [_columns objectAtIndex: columnIndex];
FOR_IN(NSGridCell*, c, _cells)
{
if ([c column] == col)
{
[result addObject: c];
}
}
END_FOR_IN(_cells);
return result;
}
- (NSArray *) _viewsForColumnAtIndex: (NSUInteger)columnIndex
{
NSArray *cells = [self _cellsForColumnAtIndex: columnIndex];
NSMutableArray *result = [NSMutableArray arrayWithCapacity: [_rows count]];
FOR_IN(NSGridCell*, c, cells)
{
NSView *v = [c contentView];
if (c != nil)
{
[result addObject: v];
}
else
{
[result addObject: [NSGridCell emptyContentView]];
}
}
END_FOR_IN(cells);
return result;
}
@end
// Private methods...
@implementation NSGridCell (Private)
- (void) _setOwningRow: (NSGridRow *)r
{
_owningRow = r;
}
- (void) _setOwningColumn: (NSGridColumn *)c
{
_owningColumn = c;
}
@end
@implementation NSGridView
+ (void) initialize
{
if (self == [NSGridView class])
{
[self setVersion: 1];
}
}
- (void) _refreshCells
{
if ([self isHidden])
{
return;
}
else
{
NSUInteger i = 0;
NSUInteger num_col = [self numberOfColumns];
NSRect f = [self frame];
CGFloat current_x = 0.0, current_y = f.size.height;
NSRect p = [self _prototypeFrame];
// Format the grid...
FOR_IN(NSGridCell*, c, _cells)
{
NSView *v = [c contentView];
NSUInteger ri = 0, ci = 0;
// Get row and column index...
ci = i % num_col;
ri = i / num_col;
// Get the row and col...
NSGridRow *row = [self rowAtIndex: ri];
NSGridColumn *col = [self columnAtIndex: ci];
NSRect rect = NSZeroRect;
if (v != nil)
{
rect = [v frame];
}
if (ci == 0)
{
current_y -= [row topPadding];
current_y -= p.size.height;
current_x = 0.0;
}
// current_x += [col leadingPadding];
if (v != nil)
{
rect = p;
rect.origin.x = current_x;
rect.origin.y = current_y;
[v setFrame: rect];
[self addSubview: v];
}
current_x += [col leadingPadding];
current_x += p.size.width;
current_x += [col trailingPadding];
if (ci == 0)
{
current_y -= [row bottomPadding];
}
// inc
i++;
}
END_FOR_IN(_cells);
}
}
- (instancetype) initWithFrame: (NSRect)frameRect
{
self = [super initWithFrame: frameRect];
if (self != nil)
{
_rows = [[NSMutableArray alloc] init];
_columns = [[NSMutableArray alloc] init];
_cells = [[NSMutableArray alloc] init];
}
return self;
}
- (instancetype) initWithViews: (NSArray *)views // an array of arrays
{
self = [self initWithFrame: NSZeroRect];
if (self == nil)
{
return self;
}
NSUInteger c = 0;
NSUInteger r = 0;
FOR_IN(NSArray*, row, views)
{
NSGridRow *gr = [[NSGridRow alloc] init];
[gr setGridView: self];
[_rows addObject: gr];
RELEASE(gr);
c = 0;
FOR_IN(NSView*, v, row)
{
NSGridColumn *gc = nil;
NSGridCell *cell = [[NSGridCell alloc] init];
if (r == 0) // first row, create all of the columns...
{
gc = [[NSGridColumn alloc] init];
[_columns addObject: gc];
RELEASE(gc);
[gc setGridView: self];
}
else
{
gc = [_columns objectAtIndex: c];
}
[cell _setOwningRow: gr];
[cell _setOwningColumn: gc];
[cell setContentView: v];
[_cells addObject: cell];
c++;
}
END_FOR_IN(row);
r++;
}
END_FOR_IN(views);
[self _refreshCells];
return self;
}
+ (instancetype) gridViewWithNumberOfColumns: (NSInteger)columnCount rows: (NSInteger)rowCount
{
NSUInteger r = 0;
NSUInteger c = 0;
NSMutableArray *rows = [[NSMutableArray alloc] initWithCapacity: rowCount];
for (r = 0; r < rowCount; r++)
{
NSMutableArray *col = [[NSMutableArray alloc] initWithCapacity: columnCount];
for (c = 0; c < columnCount; c++)
{
NSView *gv = [[NSView alloc] init];
[col addObject: gv];
RELEASE(gv);
}
[rows addObject: col];
}
return [self gridViewWithViews: rows];
}
+ (instancetype) gridViewWithViews: (NSArray *)views
{
return AUTORELEASE([[self alloc] initWithViews: views]);
}
- (void) setFrame: (NSRect)f
{
[super setFrame: f];
[self _refreshCells];
}
- (NSInteger) numberOfRows
{
return [_rows count];
}
- (NSInteger) numberOfColumns
{
return [_columns count];
}
- (NSGridRow *) rowAtIndex: (NSInteger)index
{
return [_rows objectAtIndex: index];
}
- (NSInteger) indexOfRow: (NSGridRow *)row
{
return [_rows indexOfObject: row];
}
- (NSGridColumn *) columnAtIndex: (NSInteger)index
{
return [_columns objectAtIndex: index];
}
- (NSInteger) indexOfColumn: (NSGridColumn *)column
{
return [_columns indexOfObject: column];
}
- (NSGridCell *) cellAtColumnIndex: (NSInteger)columnIndex rowIndex: (NSInteger)rowIndex
{
NSUInteger idx = rowIndex * [self numberOfColumns] + columnIndex;
return [_cells objectAtIndex: idx];
}
- (NSGridCell *) cellForView: (NSView*)view
{
NSGridCell *result = nil;
FOR_IN(NSGridCell*, c, _cells)
{
NSView *v = [c contentView];
if (v == view)
{
result = c;
break;
}
}
END_FOR_IN(_cells);
return result;
}
- (NSGridRow *) addRowWithViews: (NSArray *)views
{
return [self insertRowAtIndex: [self numberOfRows]
withViews: views];
}
- (NSGridRow *) _insertRowAtIndex: (NSInteger)index withCells: (NSArray *)cells
{
NSGridRow *gr = [[NSGridRow alloc] init];
// Insert the row and release...
[_rows insertObject: gr atIndex: index];
[gr setGridView: self];
RELEASE(gr);
NSUInteger i = 0;
NSUInteger pos = index * [self numberOfColumns];
for(i = 0; i < [self numberOfColumns]; i++)
{
NSGridCell *c = nil;
NSGridColumn *col = [_columns objectAtIndex: i];
if (i > ([cells count] - 1))
{
c = AUTORELEASE([[NSGridCell alloc] init]);
}
else
{
c = [cells objectAtIndex: i];
}
[c _setOwningRow: gr];
[c _setOwningColumn: col];
[_cells insertObject: c
atIndex: pos + i];
}
// Refresh...
[self _refreshCells];
return gr;
}
- (NSGridRow *) insertRowAtIndex: (NSInteger)index withViews: (NSArray *)views
{
NSRect f = [self _prototypeFrame];
NSMutableArray *cells = [NSMutableArray arrayWithCapacity: [views count]];
FOR_IN(NSView*, v, views)
{
NSGridCell *c = [[NSGridCell alloc] init];
[v setFrame: f];
[c setContentView: v];
[cells addObject: c];
RELEASE(c);
}
END_FOR_IN(views);
return [self _insertRowAtIndex: index withCells: cells];
}
- (void) moveRowAtIndex: (NSInteger)fromIndex toIndex: (NSInteger)toIndex
{
NSArray *cells = [self _cellsForRowAtIndex: fromIndex];
[self removeRowAtIndex: fromIndex];
[self _insertRowAtIndex: toIndex withCells: cells];
}
- (void) removeRowAtIndex: (NSInteger)index
{
NSArray *objs = [self _cellsForRowAtIndex: index];
[_rows removeObjectAtIndex: index];
[_cells removeObjectsInArray: objs];
[self _refreshCells];
}
- (NSGridColumn *) addColumnWithViews: (NSArray*)views
{
return [self insertColumnAtIndex: [self numberOfColumns]
withViews: views];
}
- (NSGridColumn *) _insertColumnAtIndex: (NSInteger)index withCells: (NSArray *)cells
{
NSGridColumn *gc = [[NSGridColumn alloc] init];
// Insert the row and release...
[_columns insertObject: gc atIndex: index];
[gc setGridView: self];
RELEASE(gc);
NSUInteger i = 0;
NSUInteger pos = index;
for(i = 0; i < [self numberOfRows]; i++)
{
NSGridCell *c = nil;
NSGridRow *row = [_rows objectAtIndex: i];
if (i > ([cells count] - 1))
{
c = AUTORELEASE([[NSGridCell alloc] init]);
}
else
{
c = [cells objectAtIndex: i];
}
[c _setOwningRow: row];
[c _setOwningColumn: gc];
[_cells insertObject: c
atIndex: pos + i * [self numberOfColumns]];
}
// Refresh...
[self _refreshCells];
return gc;
}
- (NSGridColumn *) insertColumnAtIndex: (NSInteger)index withViews: (NSArray *)views
{
NSRect f = [self _prototypeFrame];
NSMutableArray *cells = [NSMutableArray arrayWithCapacity: [views count]];
FOR_IN(NSView*, v, views)
{
NSGridCell *c = [[NSGridCell alloc] init];
[v setFrame: f];
[c setContentView: v];
[cells addObject: c];
RELEASE(c);
}
END_FOR_IN(views);
return [self _insertColumnAtIndex: index withCells: cells];
}
- (void) moveColumnAtIndex: (NSInteger)fromIndex toIndex: (NSInteger)toIndex
{
NSArray *cells = [self _cellsForColumnAtIndex: fromIndex];
[self removeColumnAtIndex: fromIndex];
[self _insertColumnAtIndex: toIndex withCells: cells];
}
- (void) removeColumnAtIndex: (NSInteger)index
{
NSArray *objs = [self _cellsForColumnAtIndex: index];
[_columns removeObjectAtIndex: index];
[_cells removeObjectsInArray: objs];
[self _refreshCells];
}
- (NSGridCellPlacement) xPlacement
{
return _xPlacement;
}
- (void) setXPlacement: (NSGridCellPlacement)x
{
_xPlacement = x;
}
- (NSGridCellPlacement) yPlacement
{
return _yPlacement;
}
- (void) setYPlacement: (NSGridCellPlacement)y
{
_yPlacement = y;
}
- (NSGridRowAlignment) rowAlignment
{
return _rowAlignment;
}
- (void) setRowAlignment: (NSGridRowAlignment)a
{
_rowAlignment = a;
}
- (CGFloat) rowSpacing
{
return _rowSpacing;
}
- (void) setRowSpacing: (CGFloat)f
{
_rowSpacing = f;
}
- (CGFloat) columnSpacing
{
return _columnSpacing;
}
- (void) setColumnSpacing: (CGFloat)f
{
_columnSpacing = f;
}
- (void) mergeCellsInHorizontalRange: (NSRange)hRange verticalRange: (NSRange)vRange
{
NSLog(@"Method %@ unimplemented.", NSStringFromSelector(_cmd));
}
// coding
- (void) encodeWithCoder: (NSCoder *)coder
{
[super encodeWithCoder: coder];
if ([coder allowsKeyedCoding])
{
[coder encodeInteger: _rowAlignment
forKey: @"NSGrid_alignment"];
[coder encodeDouble: _columnSpacing
forKey: @"NSGrid_columnSpacing"];
[coder encodeObject: _columns
forKey: @"NSGrid_columns"];
[coder encodeDouble: _rowSpacing
forKey: @"NSGrid_rowSpacing"];
[coder encodeObject: _rows
forKey: @"NSGrid_rows"];
[coder encodeInteger: _xPlacement
forKey: @"NSGrid_xPlacement"];
[coder encodeInteger: _yPlacement forKey: @"NSGrid_yPlacement"];
[coder encodeObject: _cells
forKey: @"NSGrid_cells"];
}
else
{
[coder encodeValueOfObjCType: @encode(NSUInteger)
at: &_rowAlignment];
[coder encodeObject: _columns];
[coder encodeObject: _rows];
[coder encodeObject: _cells];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_columnSpacing];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_rowSpacing];
[coder encodeValueOfObjCType: @encode(NSUInteger)
at: &_xPlacement];
[coder encodeValueOfObjCType: @encode(NSUInteger)
at: &_yPlacement];
}
}
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super initWithCoder: coder];
if (self != nil)
{
if ([coder allowsKeyedCoding])
{
if ([coder containsValueForKey: @"NSGrid_alignment"])
{
_rowAlignment = (NSGridRowAlignment)[coder decodeIntegerForKey: @"NSGrid_alignment"];
}
if ([coder containsValueForKey: @"NSGrid_columns"])
{
ASSIGN(_columns, [coder decodeObjectForKey: @"NSGrid_columns"]);
}
if ([coder containsValueForKey: @"NSGrid_rows"])
{
ASSIGN(_rows, [coder decodeObjectForKey: @"NSGrid_rows"]);
}
if ([coder containsValueForKey: @"NSGrid_cells"])
{
ASSIGN(_cells, [coder decodeObjectForKey: @"NSGrid_cells"]);
}
if ([coder containsValueForKey: @"NSGrid_columnSpacing"])
{
_columnSpacing = [coder decodeFloatForKey: @"NSGrid_columnSpacing"];
}
if ([coder containsValueForKey: @"NSGrid_rowSpacing"])
{
_rowSpacing = [coder decodeFloatForKey: @"NSGrid_rowSpacing"];
}
if ([coder containsValueForKey: @"NSGrid_xPlacement"])
{
_xPlacement = [coder decodeIntegerForKey: @"NSGrid_xPlacement"];
}
if ([coder containsValueForKey: @"NSGrid_yPlacement"])
{
_yPlacement = [coder decodeIntegerForKey: @"NSGrid_yPlacement"];
}
}
else
{
[coder decodeValueOfObjCType: @encode(NSUInteger)
at: &_rowAlignment];
ASSIGN(_columns, [coder decodeObject]);
ASSIGN(_rows, [coder decodeObject]);
ASSIGN(_cells, [coder decodeObject]);
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_columnSpacing];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_rowSpacing];
[coder decodeValueOfObjCType: @encode(NSUInteger)
at: &_xPlacement];
[coder decodeValueOfObjCType: @encode(NSUInteger)
at: &_yPlacement];
}
}
[self _refreshCells];
return self;
}
- (void) dealloc
{
RELEASE(_columns);
RELEASE(_rows);
RELEASE(_cells);
[super dealloc];
}
@end
/// Cell ///
@implementation NSGridCell
+ (void) initialize
{
if (self == [NSGridCell class])
{
[self setVersion: 1];
}
}
- (NSView *) contentView
{
return _contentView;
}
- (void) setContentView: (NSView *)v
{
ASSIGN(_contentView, v);
}
+ (NSView *) emptyContentView
{
return AUTORELEASE([[NSView alloc] initWithFrame: NSZeroRect]);
}
// Weak references to row/column
- (NSGridRow *) row
{
return _owningRow;
}
- (NSGridColumn *) column
{
return _owningColumn;
}
// Placement
- (NSGridCellPlacement) xPlacement
{
return _xPlacement;
}
- (void) setXPlacement: (NSGridCellPlacement)x
{
_xPlacement = x;
}
- (NSGridCellPlacement) yPlacement
{
return _yPlacement;
}
- (void) setYPlacement: (NSGridCellPlacement)y
{
_yPlacement = y;
}
- (NSGridRowAlignment) rowAlignment
{
return _rowAlignment;
}
- (void) setRowAlignment: (NSGridRowAlignment)a
{
_rowAlignment = a;
}
// Constraints
- (NSArray *) customPlacementConstraints
{
return _customPlacementConstraints;
}
- (void) setCustomPlacementConstraints: (NSArray *)constraints
{
ASSIGNCOPY(_customPlacementConstraints, constraints);
}
// coding
- (void) encodeWithCoder: (NSCoder *)coder
{
if ([coder allowsKeyedCoding])
{
[coder encodeObject: _contentView
forKey: @"NSGrid_content"];
[coder encodeObject: _mergeHead
forKey: @"NSGrid_mergeHead"];
[coder encodeObject: _owningRow
forKey: @"NSGrid_owningRow"]; // weak
[coder encodeObject: _owningColumn
forKey: @"NSGrid_owningColumn"]; // weak
[coder encodeInteger: _xPlacement
forKey: @"NSGrid_xPlacement"];
[coder encodeInteger: _yPlacement
forKey: @"NSGrid_yPlacement"];
[coder encodeInteger: _rowAlignment
forKey: @"NSGrid_alignment"];
}
else
{
[coder encodeObject: [self contentView]];
[coder encodeObject: _mergeHead];
[coder encodeObject: _owningRow];
[coder encodeObject: _owningColumn];
[coder encodeObject: _customPlacementConstraints];
[coder encodeValueOfObjCType:@encode(NSInteger)
at: &_xPlacement];
[coder encodeValueOfObjCType:@encode(NSInteger)
at: &_yPlacement];
[coder encodeValueOfObjCType:@encode(NSInteger)
at: &_rowAlignment];
}
}
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super init];
if (self != nil)
{
if ([coder allowsKeyedCoding])
{
if ([coder containsValueForKey: @"NSGrid_content"])
{
[self setContentView: [coder decodeObjectForKey: @"NSGrid_content"]];
}
if ([coder containsValueForKey: @"NSGrid_mergeHead"])
{
_mergeHead = [coder decodeObjectForKey: @"NSGrid_mergeHead"];
}
if ([coder containsValueForKey: @"NSGrid_owningRow"])
{
_owningRow = [coder decodeObjectForKey: @"NSGrid_owningRow"]; // weak
}
if ([coder containsValueForKey: @"NSGrid_owningColumn"])
{
_owningColumn = [coder decodeObjectForKey: @"NSGrid_owningColumn"]; // weak
}
if ([coder containsValueForKey: @"NSGrid_xPlacement"])
{
_xPlacement = [coder decodeIntegerForKey: @"NSGrid_xPlacement"];
}
if ([coder containsValueForKey: @"NSGrid_yPlacement"])
{
_yPlacement = [coder decodeIntegerForKey: @"NSGrid_yPlacement"];
}
if ([coder containsValueForKey: @"NSGrid_alignment"])
{
_rowAlignment = [coder decodeIntegerForKey: @"NSGrid_alignment"];
}
}
else
{
[self setContentView: [coder decodeObject]];
ASSIGN(_mergeHead, [coder decodeObject]);
_owningRow = [coder decodeObject]; // weak
_owningColumn = [coder decodeObject]; // weak
ASSIGN(_customPlacementConstraints, [coder decodeObject]);
[coder decodeValueOfObjCType: @encode(NSInteger)
at: &_xPlacement];
[coder decodeValueOfObjCType:@encode(NSInteger)
at: &_yPlacement];
[coder decodeValueOfObjCType:@encode(NSInteger)
at: &_rowAlignment];
}
}
return self;
}
- (void) dealloc
{
RELEASE(_contentView);
RELEASE(_mergeHead);
[super dealloc];
}
@end
/// Column ///
@implementation NSGridColumn
+ (void) initialize
{
if (self == [NSGridColumn class])
{
[self setVersion: 1];
}
}
- (void) setGridView: (NSGridView *)gv
{
_gridView = gv;
}
- (NSGridView *) gridView
{
return _gridView;
}
- (NSInteger) numberOfCells
{
// The number of cells in a column = # of rows
return [_gridView numberOfRows];
}
- (NSGridCell *) cellAtIndex: (NSInteger)index
{
NSUInteger ci = [_gridView indexOfColumn: self];
// First we get the columnIndex (ci) then we get the member of that column
// referred to by index. The method called here gets the correct cell out of
// the _cells array in the containing NSGridView.
return [_gridView cellAtColumnIndex: ci
rowIndex: index];
}
- (NSGridCellPlacement) xPlacement
{
return _xPlacement;
}
- (void) setXPlacement: (NSGridCellPlacement)x
{
_xPlacement = x;
}
- (CGFloat) width
{
return _width;
}
- (void) setWidth: (CGFloat)f
{
_width = f;
}
- (CGFloat) leadingPadding
{
return _leadingPadding;
}
- (void) setLeadingPadding: (CGFloat)f
{
_leadingPadding = f;
}
- (CGFloat) trailingPadding
{
return _trailingPadding;
}
- (void) setTrailingPadding: (CGFloat)f
{
_trailingPadding = f;
}
- (BOOL) isHidden
{
return _isHidden;
}
- (void) mergeCellsInRange: (NSRange)range
{
NSUInteger ci = [_gridView indexOfColumn: self];
NSRange hRange = NSMakeRange(ci, 1);
[_gridView mergeCellsInHorizontalRange: hRange
verticalRange: range];
}
// coding
- (void) encodeWithCoder: (NSCoder *)coder
{
if ([coder allowsKeyedCoding])
{
[coder encodeBool: _isHidden
forKey: @"NSGrid_hidden"];
[coder encodeFloat: _leadingPadding
forKey: @"NSGrid_leadingPadding"];
[coder encodeObject: _gridView
forKey: @"NSGrid_owningGrid"]; // weak
[coder encodeFloat: _trailingPadding
forKey: @"NSGrid_trailingPadding"];
[coder encodeFloat: _width
forKey: @"NSGrid_width"];
[coder encodeInteger: _xPlacement
forKey: @"NSGrid_xPlacement"];
}
else
{
[coder encodeValueOfObjCType: @encode(BOOL)
at: &_isHidden];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_leadingPadding];
[coder encodeObject: _gridView];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_trailingPadding];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_width];
[coder encodeValueOfObjCType: @encode(NSInteger)
at: &_xPlacement];
}
}
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super init];
if (self != nil)
{
if ([coder allowsKeyedCoding])
{
if ([coder containsValueForKey: @"NSGrid_hidden"])
{
_isHidden = [coder decodeBoolForKey: @"NSGrid_hidden"];
}
if ([coder containsValueForKey: @"NSGrid_leadingPadding"])
{
_leadingPadding = [coder decodeFloatForKey: @"NSGrid_leadingPadding"];
}
if ([coder containsValueForKey: @"NSGrid_owningGrid"])
{
_gridView = [coder decodeObjectForKey: @"NSGrid_owningGrid"]; // weak
}
if ([coder containsValueForKey: @"NSGrid_trailingPadding"])
{
_trailingPadding = [coder decodeFloatForKey: @"NSGrid_trailingPadding"];
}
if ([coder containsValueForKey: @"NSGrid_width"])
{
_width = [coder decodeFloatForKey: @"NSGrid_width"];
}
if ([coder containsValueForKey: @"NSGrid_xPlacement"])
{
_xPlacement = [coder decodeIntegerForKey: @"NSGrid_xPlacement"];
}
}
else
{
[coder decodeValueOfObjCType: @encode(BOOL)
at: &_isHidden];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_leadingPadding];
_gridView = [coder decodeObject];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_trailingPadding];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_width];
[coder decodeValueOfObjCType: @encode(NSInteger)
at: &_xPlacement];
}
}
return self;
}
@end
/// Row ///
@implementation NSGridRow
+ (void) initialize
{
if (self == [NSGridRow class])
{
[self setVersion: 1];
}
}
- (void) setGridView: (NSGridView *)gridView
{
_gridView = gridView; // weak reference...
}
- (NSGridView *) gridView
{
return _gridView;
}
- (NSInteger) numberOfCells
{
// The number of cells in a row = # of columns
return [_gridView numberOfColumns];
}
- (NSGridCell *) cellAtIndex: (NSInteger)index
{
NSUInteger ri = [_gridView indexOfRow: self];
// First we get the rowIndex (ri) then we get the member of that row
// referred to by index. The method called here gets the correct cell out of
// the _cells array in the containing NSGridView.
return [_gridView cellAtColumnIndex: index
rowIndex: ri];
}
- (NSGridCellPlacement) yPlacement
{
return _yPlacement;
}
- (void) setYPlacement: (NSGridCellPlacement)y
{
_yPlacement = y;
}
- (CGFloat) height
{
return _height;
}
- (void) setHeight: (CGFloat)f
{
_height = f;
}
- (CGFloat) topPadding
{
return _topPadding;
}
- (void) setTopPadding: (CGFloat)f
{
_topPadding = f;
}
- (CGFloat) bottomPadding
{
return _bottomPadding;
}
- (void) setBottomPadding: (CGFloat)f
{
_bottomPadding = f;
}
- (BOOL) isHidden
{
return _isHidden;
}
- (void) setHidden: (BOOL)flag
{
_isHidden = flag;
}
- (void) mergeCellsInRange: (NSRange)range
{
NSUInteger ri = [_gridView indexOfRow: self];
NSRange vRange = NSMakeRange(ri, 1);
[_gridView mergeCellsInHorizontalRange: range
verticalRange: vRange];
}
// coding
- (void) encodeWithCoder: (NSCoder *)coder
{
if ([coder allowsKeyedCoding])
{
[coder encodeBool: _isHidden forKey: @"NSGrid_hidden"];
[coder encodeFloat: _bottomPadding forKey: @"NSGrid_bottomPadding"];
[coder encodeObject: _gridView forKey: @"NSGrid_owningGrid"];
[coder encodeFloat: _topPadding forKey: @"NSGrid_topPadding"];
[coder encodeFloat: _height forKey: @"NSGrid_height"];
[coder encodeFloat: _yPlacement forKey: @"NSGrid_yPlacement"];
}
else
{
[coder encodeValueOfObjCType: @encode(BOOL)
at: &_isHidden];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_bottomPadding];
[coder encodeObject: _gridView];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_topPadding];
[coder encodeValueOfObjCType: @encode(CGFloat)
at: &_height];
[coder encodeValueOfObjCType: @encode(NSInteger)
at: &_yPlacement];
}
}
- (instancetype) initWithCoder: (NSCoder *)coder
{
self = [super init];
if (self != nil)
{
if ([coder allowsKeyedCoding])
{
if ([coder containsValueForKey: @"NSGrid_hidden"])
{
_isHidden = [coder decodeBoolForKey: @"NSGrid_hidden"];
}
if ([coder containsValueForKey: @"NSGrid_bottomPadding"])
{
_bottomPadding = [coder decodeFloatForKey: @"NSGrid_bottomPadding"];
}
if ([coder containsValueForKey: @"NSGrid_owningGrid"])
{
_gridView = [coder decodeObjectForKey: @"NSGrid_owningGrid"];
}
if ([coder containsValueForKey: @"NSGrid_topPadding"])
{
_topPadding = [coder decodeFloatForKey: @"NSGrid_topPadding"];
}
if ([coder containsValueForKey: @"NSGrid_height"])
{
_height = [coder decodeFloatForKey: @"NSGrid_height"];
}
if ([coder containsValueForKey: @"NSGrid_yPlacement"])
{
_yPlacement = [coder decodeFloatForKey: @"NSGrid_yPlacement"];
}
}
else
{
[coder decodeValueOfObjCType: @encode(BOOL)
at: &_isHidden];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_bottomPadding];
_gridView = [coder decodeObject];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_topPadding];
[coder decodeValueOfObjCType: @encode(CGFloat)
at: &_height];
[coder decodeValueOfObjCType: @encode(NSInteger)
at: &_yPlacement];
}
}
return self;
}
@end