diff --git a/AppKit/AppKit.j b/AppKit/AppKit.j
index f55770a32..fdb8827a3 100644
--- a/AppKit/AppKit.j
+++ b/AppKit/AppKit.j
@@ -58,6 +58,8 @@
@import "CPSlider.j"
@import "CPSplitView.j"
@import "CPTabView.j"
+@import "CPTableColumn.j"
+@import "CPTableView.j"
@import "CPTextField.j"
@import "CPToolbar.j"
@import "CPToolbarItem.j"
diff --git a/AppKit/AppKit.steam b/AppKit/AppKit.steam
index f430b53d7..cd17cd577 100644
--- a/AppKit/AppKit.steam
+++ b/AppKit/AppKit.steam
@@ -11,9 +11,6 @@
AppKit
Excluded
- CPOutlineView.j
- CPTableColumn.j
- CPTableView.j
Themes
CoreGraphics/CGContextCanvas.j
diff --git a/AppKit/CPClipView.j b/AppKit/CPClipView.j
index a525716a0..51264f7ce 100644
--- a/AppKit/CPClipView.j
+++ b/AppKit/CPClipView.j
@@ -188,27 +188,7 @@ var CPClipViewDocumentViewKey = @"CPScrollViewDocumentView";
{
if (self = [super initWithCoder:aCoder])
{
- _documentView = [aCoder decodeObjectForKey:CPClipViewDocumentViewKey];
-
- if (_documentView)
- {
- [_documentView setPostsFrameChangedNotifications:YES];
- [_documentView setPostsBoundsChangedNotifications:YES];
-
- var defaultCenter = [CPNotificationCenter defaultCenter];
-
- [defaultCenter
- addObserver:self
- selector:@selector(viewFrameChanged:)
- name:CPViewFrameDidChangeNotification
- object:_documentView];
-
- [defaultCenter
- addObserver:self
- selector:@selector(viewBoundsChanged:)
- name:CPViewBoundsDidChangeNotification
- object:_documentView];
- }
+ [self setDocumentView:[aCoder decodeObjectForKey:CPClipViewDocumentViewKey]];
}
return self;
diff --git a/AppKit/CPTableColumn.j b/AppKit/CPTableColumn.j
index 1421eecb1..a286a315d 100644
--- a/AppKit/CPTableColumn.j
+++ b/AppKit/CPTableColumn.j
@@ -68,11 +68,11 @@ CPTableColumnUserResizingMask = 2;
unsigned _resizingMask;
- CPView _dataView;
+ CPView _dataView; // default data view for this column
- Object _dataViewData;
- Object _dataViewForView;
- Object _purgableInfosForDataView;
+ Object _dataViewData; // cache of data view archives (key=data view hash, value=data view archive)
+ Object _dataViewForView; // mapping from view instances back to their data view prototype (key=view instance hash, value=data view)
+ Object _purgableInfosForDataView; // (key=data view hash, value=)
}
/*!
@@ -86,17 +86,18 @@ CPTableColumnUserResizingMask = 2;
if (self)
{
+ [self _init];
+
_identifier = anIdentifier;
_width = 40.0;
_minWidth = 8.0;
_maxWidth = 1000.0;
- _dataViewData = {};
- _dataViewForView = {};
- _purgableInfosForDataView = {};
+ var dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
+ [dataView setValue:[CPColor whiteColor] forThemedAttributeName:"text-color" inControlState:CPControlStateHighlighted];
- [self setDataView:[[CPTextField alloc] initWithFrame:CPRectMakeZero()]];
+ [self setDataView:dataView];
_headerView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
[_headerView setBackgroundColor:[CPColor greenColor]];
@@ -105,6 +106,13 @@ CPTableColumnUserResizingMask = 2;
return self;
}
+- (void)_init
+{
+ _dataViewData = {};
+ _dataViewForView = {};
+ _purgableInfosForDataView = {};
+}
+
/*!
Sets the table column's identifier
@param anIdentifier the new identifier
@@ -317,7 +325,7 @@ CPTableColumnUserResizingMask;
{
return [self dataCellForRow:aRowIndex];
}
-
+/*
- (void)_markViewAsPurgable:(CPView)aView
{
var viewHash = [aView hash],
@@ -328,7 +336,7 @@ CPTableColumnUserResizingMask;
[_purgableInfosForDataView[dataViewHash] setObject:aView forKey:viewHash];
}
-
+*/
- (void)_markView:(CPView)aView inRow:(unsigned)aRow asPurgable:(BOOL)isPurgable
{
var viewHash = [aView hash],
@@ -339,55 +347,93 @@ CPTableColumnUserResizingMask;
if (!isPurgable)
return;
- _purgableInfosForDataView[dataViewHash] = [CPDictionary dictionary];
+ _purgableInfosForDataView[dataViewHash] = {};
}
if (!isPurgable)
- [_purgableInfosForDataView[dataViewHash] removeObjectForKey:viewHash];
+ delete _purgableInfosForDataView[dataViewHash][viewHash];
else
- [_purgableInfosForDataView[dataViewHash] setObject:PurgableInfoMake(aView, aRow) forKey:viewHash];
+ _purgableInfosForDataView[dataViewHash][viewHash] = PurgableInfoMake(aView, aRow);
}
- (CPView)_newDataViewForRow:(int)aRowIndex avoidingRows:(CPRange)rows
{
var view = [self dataViewForRow:aRowIndex],
viewHash = [view hash],
- dataViewHash = [_dataViewForView[viewHash] hash],
- purgableInfos = _purgableInfosForDataView[dataViewHash];
- //console.warn("ok, a cell is needed");
- if (purgableInfos && [purgableInfos count])
- {//console.warn("yes, inside");
- var keys = [purgableInfos allKeys],
- count = keys.length;
-
- while (count--)
+ purgableInfos = _purgableInfosForDataView[viewHash];
+
+ if (purgableInfos)
+ {
+ for (var key in purgableInfos)
{
- var key = keys[count],
- info = [purgableInfos objectForKey:key];
-
- [purgableInfos removeObjectForKey:key];
-
- if (CPLocationInRange(PurgableInfoRow(info), rows))
- continue;
- //console.warn("yes, a purged view is usable, its called" + PurgableInfoView(info));
- return PurgableInfoView(info);
+ var info = purgableInfos[key];
+ if (!CPLocationInRange(PurgableInfoRow(info), rows))
+ {
+ //CPLog.debug("yes, a purged view is usable, its called: " + PurgableInfoView(info));
+ delete purgableInfos[key];
+ return PurgableInfoView(info);
+ }
}
}
- var data = _dataViewData[viewHash];
-
- if (!data)
- {
+ // if we haven't cached an archive of the data view, do it now
+ if (!_dataViewData[viewHash])
_dataViewData[viewHash] = [CPKeyedArchiver archivedDataWithRootObject:view];
- data = _dataViewData[viewHash];
- }
- //console.warn("nope, time for creation");
- return [CPKeyedUnarchiver unarchiveObjectWithData:data];
+
+ // unarchive the data view cache
+ var newView = [CPKeyedUnarchiver unarchiveObjectWithData:_dataViewData[viewHash]];
+
+ // map the new view's hash to it's data view prototype
+ _dataViewForView[[newView hash]] = view;
+
+ //CPLog.warn("nope, time for creation: %s", newView);
+
+ return newView;
}
@end
-_PurgableViewInfoMake = function(aView, aRow)
+
+var CPTableColumnIdentifierKey = @"CPTableColumnIdentifierKey",
+ CPTableColumnHeaderViewKey = @"CPTableColumnHeaderViewKey",
+ CPTableColumnDataViewKey = @"CPTableColumnDataViewKey",
+ CPTableColumnWidthKey = @"CPTableColumnWidthKey",
+ CPTableColumnMinWidthKey = @"CPTableColumnMinWidthKey",
+ CPTableColumnMaxWidthKey = @"CPTableColumnMaxWidthKey",
+ CPTableColumnResizingMaskKey = @"CPTableColumnResizingMaskKey";
+
+@implementation CPTableColumn (CPCoding)
+
+- (id)initWithCoder:(CPCoder)aCoder
{
- return { view:aView, row:aRow};
+ [self _init];
+
+ _identifier = [aCoder decodeObjectForKey:CPTableColumnIdentifierKey];
+
+ [self setHeaderView:[aCoder decodeObjectForKey:CPTableColumnHeaderViewKey]];
+ [self setDataView:[aCoder decodeObjectForKey:CPTableColumnDataViewKey]];
+
+ _width = [aCoder decodeFloatForKey:CPTableColumnWidthKey];
+ _minWidth = [aCoder decodeFloatForKey:CPTableColumnMinWidthKey];
+ _maxWidth = [aCoder decodeFloatForKey:CPTableColumnMaxWidthKey];
+
+ _resizingMask = [aCoder decodeBoolForKey:CPTableColumnResizingMaskKey];
+
+ return self;
}
+
+- (void)encodeWithCoder:(CPCoder)aCoder
+{
+ [aCoder encodeObject:_identifier forKey:CPTableColumnIdentifierKey];
+
+ [aCoder encodeObject:_headerView forKey:CPTableColumnHeaderViewKey];
+ [aCoder encodeObject:_dataView forKey:CPTableColumnDataViewKey];
+
+ [aCoder encodeObject:_width forKey:CPTableColumnWidthKey];
+ [aCoder encodeObject:_minWidth forKey:CPTableColumnMinWidthKey];
+ [aCoder encodeObject:_maxWidth forKey:CPTableColumnMaxWidthKey];
+
+ [aCoder encodeObject:_resizingMask forKey:CPTableColumnResizingMaskKey];
+}
+
+@end
diff --git a/AppKit/CPTableView.j b/AppKit/CPTableView.j
index 87362ebd5..233c15a2e 100644
--- a/AppKit/CPTableView.j
+++ b/AppKit/CPTableView.j
@@ -23,10 +23,25 @@
@import "CPControl.j"
@import "CPTableColumn.j"
-//objj_backtrace_set_enable(true);
+@import "CPColor.j"
+@import "CPTextField.j"
-#define ROW_HEIGHT(aRow) (_hasVariableHeightRows ? _rowHeights[aRow] : _rowHeight);
+#define ROW_HEIGHT(aRow) (_hasVariableHeightRows ? _rowHeights[aRow] : _rowHeight)
+#define ROW_MIN_Y(aRow) (_hasVariableHeightRows ? _rowMinYs[aRow] : (aRow * (_rowHeight + _intercellSpacing.height)))
+CPTableViewColumnDidMoveNotification = "CPTableViewColumnDidMoveNotification";
+CPTableViewColumnDidResizeNotification = "CPTableViewColumnDidResizeNotification";
+CPTableViewSelectionDidChangeNotification = "CPTableViewSelectionDidChangeNotification";
+CPTableViewSelectionIsChangingNotification = "CPTableViewSelectionIsChangingNotification";
+
+var _CPTableViewWillDisplayCellSelector = 1 << 0,
+ _CPTableViewShouldSelectRowSelector = 1 << 1,
+ _CPTableViewShouldSelectTableColumnSelector = 1 << 2,
+ _CPTableViewSelectionShouldChangeSelector = 1 << 3,
+ _CPTableViewShouldEditTableColumnSelector = 1 << 4,
+ _CPTableViewSelectionIndexesForProposedSelectionSelector = 1 << 5,
+ _CPTableViewHeightOfRowSelector = 1 << 6;
+
/*
CPTableView is located within the AppKit framework and is used to display tables. It uses a delegate model for getting its data i.e. you give it an object that provides it with the data it should display.
@@ -34,31 +49,53 @@
*/
@implementation CPTableView : CPControl
{
- id _dataSource;
+ // Archived:
- CPScrollView _scrollView;
- CPTableHeaderView _headerView;
+ id _dataSource;
+ id _delegate;
+
+ //CPTableHeaderView _headerView;
+ //CPView _cornerView;
CPArray _tableColumns;
- //
+ CPIndexSet _selectedRowIndexes;
+ //CPArray _selectedColumns;
+
+ float _rowHeight;
+ CGSize _intercellSpacing;
+
+ BOOL _allowsMultipleSelection;
+ BOOL _allowsEmptySelection;
+ //BOOL _allowsColumnReordering;
+ //BOOL _allowsColumnResizing;
+ //BOOL _allowsColumnSelection;
+ //BOOL _autoresizesAllColumnsToFit;
+
+ //CPColor _gridColor;
+ //BOOL _drawsGrid;
+
+
+ // Not archived:
+
+ int _delegateSelectorsCache;
+
+ //CPScrollView _scrollView;
+
unsigned _numberOfRows;
unsigned _numberOfColumns;
+ BOOL _hasVariableHeightRows;
+
// Heights
- float _rowHeight;
float _columnHeight; // calculated
- CPArray _rowMinYs;
CPArray _rowHeights;
-
- BOOL _hasVariableHeightRows;
+ CPArray _rowMinYs;
CPArray _tableCells;
CPArray _tableColumnViews;
- CGSize _intercellSpacing;
-
// Caching
Object _dataViewCache;
CPArray _objectValueCache;
@@ -68,6 +105,20 @@
CPRange _populatedRows;
CPRange _populatedColumns;
+
+ // Selection
+ CPIndexSet _previousSelectedRowIndexes;
+ int _selectionStartRow;
+ int _selectionModifier;
+
+ CPIndexSet _currentlySelected;
+ CPArray _selectionViews;
+ CPArray _selectionViewsPool;
+}
+
++ (void)initialize
+{
+
}
- (id)initWithFrame:(CGRect)aFrame
@@ -75,45 +126,62 @@
self = [super initWithFrame:aFrame];
if (self)
- {
- _rowHeight = 17.0;
-
- _tableCells = [];
- _tableColumns = [];
- _tableColumnViews = [];
-
- _dataViewCache = {};
- _objectValueCache = {};
-
- _intercellSpacing = CPSizeMake(3.0, 2.0);
-
- _visibleRows = CPMakeRange(0, 0);
- _visibleColumns = CPMakeRange(0, 0);
+ {
+ [self _init];
}
return self;
}
+- (void)_init
+{
+ _tableColumns = [];
+ _numberOfColumns = 0;
+
+ _selectedRowIndexes = [CPIndexSet indexSet];
+
+ _rowHeight = 17.0;
+ _intercellSpacing = CPSizeMake(3.0, 2.0);
+
+ _allowsMultipleSelection = YES;
+ _allowsEmptySelection = YES;
+
+
+ _tableCells = [];
+ _tableColumnViews = [];
+
+ _dataViewCache = {};
+ _objectValueCache = [];
+
+ _visibleRows = CPMakeRange(0, 0);
+ _visibleColumns = CPMakeRange(0, 0);
+
+ _rowHeights = [];
+ _rowMinYs = [];
+}
+
/*
Returns the table's column height
*/
- (float)_columnHeight
{
- return _numberOfRows * (_rowHeight + _intercellSpacing.height);
+ return _columnHeight;//_numberOfRows * (_rowHeight + _intercellSpacing.height);
}
- (void)newCellForRow:(unsigned)aRowIndex column:(unsigned)aColumnIndex avoidingRows:(CPRange)rows
-{//console.warn("new cell please.");
+{
var dataView = [_tableColumns[aColumnIndex] _newDataViewForRow:aRowIndex avoidingRows:rows];
-
- [dataView setFrame:CGRectMake(0.0, aRowIndex * (_rowHeight + _intercellSpacing.height), [_tableColumns[aColumnIndex] width], _rowHeight)];
- [dataView setBackgroundColor:[CPColor greenColor]];
+
+ [dataView setFrame:CGRectMake(0.0, ROW_MIN_Y(aRowIndex), [_tableColumns[aColumnIndex] width], ROW_HEIGHT(aRowIndex))];
+
+ if ([dataView respondsToSelector:@selector(highlight:)])
+ [dataView highlight:[_selectedRowIndexes containsIndex:aRowIndex]];
if (!_objectValueCache[aColumnIndex])
_objectValueCache[aColumnIndex] = [];
// We may be storing 0 after all!
- if (typeof _objectValueCache[aColumnIndex][aRowIndex] === "undefined")
+ if (_objectValueCache[aColumnIndex][aRowIndex] === undefined)
_objectValueCache[aColumnIndex][aRowIndex] = [_dataSource tableView:self objectValueForTableColumn:_tableColumns[aColumnIndex] row:aRowIndex];
[dataView setObjectValue:_objectValueCache[aColumnIndex][aRowIndex]];
@@ -128,52 +196,15 @@
// Determine new visible rows and columns.
- // Use a ambitious estimate for our starting row.
- var rowStart = MAX(FLOOR((CGRectGetMinY(aRect) + _intercellSpacing.height) / (_rowHeight + _intercellSpacing.height)), 0),
+ var rowStart = MAX(0, [self _rowAtY:CGRectGetMinY(aRect)] - 1),
+ rowEnd = MIN(_numberOfRows, [self _rowAtY:CGRectGetMaxY(aRect)] + 1),
- // Use a conservative estimate for the final row.
- rowEnd = MIN(_numberOfRows, CEIL(CGRectGetMaxY(aRect) / (_rowHeight + _intercellSpacing.height))),
-
- visibleRows = CPMakeRange(rowStart, rowEnd - rowStart);
-
- var columnStart = 0;
-
- // Iterate through all our columns until we find the first one that intersects the rect.
- while (columnStart < _numberOfColumns && !CGRectIntersectsRect([_tableColumnViews[columnStart] frame], aRect))
- ++columnStart;
-
- // Now use a binary search to find the last visible column
- // O (lg n) < O (n), but O(n) (above), so O (n + lg n) = O (n) ?
- var first = columnStart + 1,
- last = _numberOfColumns - 1;
- columnEnd = columnStart;
+ visibleRows = CPMakeRange(rowStart, rowEnd - rowStart),
- while (first <= last)
- {
- // Assume this is the one.
- var columnEnd = FLOOR((first + last) / 2),
- columnIsVisible = CGRectIntersectsRect([_tableColumnViews[columnEnd] frame], aRect);
-
- // If the column isn't visible, look left!
- if (!columnIsVisible)
- last = columnEnd - 1;
+ columnStart = MAX(0, [self _columnAtX:CGRectGetMinX(aRect)]),
+ columnEnd = MIN(_numberOfColumns, [self _columnAtX:CGRectGetMaxX(aRect)] + 1),
- // Visible, nothing to the right, found it...
- if (columnEnd + 1 >= _numberOfColumns)
- break;
-
- // Visible, column to the right is NOT visible, found it! (the good way)
- if (!CGRectIntersectsRect([_tableColumnViews[columnEnd + 1] frame], aRect))
- break;
-
- // If not, look right! (2 since we checked the dude to the right already)
- first = columnEnd + 2;
- }
-
- // columnEnd is our "count" in loops.
- ++columnEnd;
-
- var visibleColumns = CPMakeRange(columnStart, columnEnd - columnStart);
+ visibleColumns = CPMakeRange(columnStart, columnEnd - columnStart);
if (CPEqualRanges(_visibleRows, visibleRows) && CPEqualRanges(_visibleColumns, visibleColumns))
return;
@@ -182,9 +213,9 @@
unionVisibleColumns = CPUnionRange(_visibleColumns, visibleColumns);
// Determine whether to use 2 sweeps or one. If we have lots of overlap of cells, use just one.
- if (unionVisibleRows.length * unionVisibleColumns.length <=
- (_visibleRows.length + visibleRows.length) * (_visibleColumns.length + visibleColumns.length))
- {
+ //if (unionVisibleRows.length * unionVisibleColumns.length <=
+ // (_visibleRows.length * _visibleColumns.length) + (visibleRows.length * visibleColumns.length))
+ //{
var column = unionVisibleColumns.location,
columnEnd = CPMaxRange(unionVisibleColumns),
@@ -222,11 +253,9 @@
}
}
}
- }
- else
- {
-
- }
+ //}
+ //else
+ // CPLog.error("CPTable double sweep not implemented");
_visibleRows = visibleRows;
_visibleColumns = visibleColumns;
@@ -318,6 +347,8 @@
[_tableCells[i][j] setFrameOrigin:CPPointMake(0.0, y)];
}
}
+
+ // FIXME: variable height rows
}
_intercellSpacing = CPSizeCreateCopy(aSize);
@@ -343,11 +374,12 @@
_rowHeight = aRowHeight;
- var row = 0,
- column = 0;
-
- for (; row < _numberOfRows; ++row)
- for (column = 0; column < _numberOfColumns; ++column)
+ // don't perform adjustments if we're using variable height rows
+ if (_hasVariableHeightRows)
+ return;
+
+ for (var row = 0; row < _numberOfRows; ++row)
+ for (var column = 0; column < _numberOfColumns; ++column)
[_tableCells[column][row] setFrameOrigin:CPPointMake(0.0, row * (_rowHeight + _intercellSpacing.height))];
}
@@ -379,6 +411,7 @@
[_tableCells addObject:tableColumnCells];
+ // TODO: do we really need to initialize this, or is undefined good enough?
for (; i < _numberOfRows; ++i)
_tableCells[_numberOfColumns][i] = nil;
@@ -431,6 +464,18 @@
return _tableColumns;
}
+/*
+ Returns the first CPTableColumn equal to the given object (as determined by the "isEqual:" selector), or nil if none exists.
+ @param anObject the object to look for
+*/
+- (CPTableColumn)tableColumnWithIdentifier:(id)anObject
+{
+ for (var i = 0; i < _tableColumns.length; i++)
+ if ([_tableColumns[i] isEqual:anObject])
+ return _tableColumns[i];
+ return nil;
+}
+
// Getting the dimensions of the table
/*
Returns the number of columns in the table
@@ -489,6 +534,67 @@
return _dataSource;
}
+
+- (id)delegate
+{
+ return _delegate;
+}
+
+
+/*!
+ Sets the delegate for the tableview.
+*/
+- (void)setDelegate:(id)aDelegate
+{
+ if (_delegate === aDelegate)
+ return;
+
+ var notificationCenter = [CPNotificationCenter defaultCenter];
+
+ if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
+ [notificationCenter removeObserver:_delegate name:CPTableViewColumnDidMoveNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
+ [notificationCenter removeObserver:_delegate name:CPTableViewColumnDidResizeNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
+ [notificationCenter removeObserver:_delegate name:CPTableViewSelectionDidChangeNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
+ [notificationCenter removeObserver:_delegate name:CPTableViewSelectionIsChangingNotification object:self];
+
+ _delegate = aDelegate;
+
+ if ([_delegate respondsToSelector:@selector(tableViewColumnDidMove:)])
+ [notificationCenter addObserver:_delegate selector:@selector(tableViewColumnDidMove:) name:CPTableViewColumnDidMoveNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewColumnDidResize:)])
+ [notificationCenter addObserver:_delegate selector:@selector(tableViewColumnDidResize:) name:CPTableViewColumnDidResizeNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewSelectionDidChange:)])
+ [notificationCenter addObserver:_delegate selector:@selector(tableViewSelectionDidChange:) name:CPTableViewSelectionDidChangeNotification object:self];
+ if ([_delegate respondsToSelector:@selector(tableViewSelectionIsChanging:)])
+ [notificationCenter addObserver:_delegate selector:@selector(tableViewSelectionIsChanging:) name:CPTableViewSelectionIsChangingNotification object:self];
+
+ _delegateSelectorsCache = 0;
+
+ if ([_delegate respondsToSelector:@selector(tableView:willDisplayCell:forTableColumn:row:)])
+ _delegateSelectorsCache |= _CPTableViewWillDisplayCellSelector;
+ if ([_delegate respondsToSelector:@selector(tableView:shouldSelectRow:)])
+ _delegateSelectorsCache |= _CPTableViewShouldSelectRowSelector;
+ if ([_delegate respondsToSelector:@selector(tableView:shouldSelectTableColumn:)])
+ _delegateSelectorsCache |= _CPTableViewShouldSelectTableColumnSelector;
+ if ([_delegate respondsToSelector:@selector(selectionShouldChangeInTableView:)])
+ _delegateSelectorsCache |= _CPTableViewSelectionShouldChangeSelector;
+ if ([_delegate respondsToSelector:@selector(tableView:shouldEditTableColumn:row:)])
+ _delegateSelectorsCache |= _CPTableViewShouldEditTableColumnSelector;
+ if ([_delegate respondsToSelector:@selector(tableView:selectionIndexesForProposedSelection:)])
+ _delegateSelectorsCache |= _CPTableViewSelectionIndexesForProposedSelectionSelector;
+ if ([_delegate respondsToSelector:@selector(tableView:heightOfRow:)])
+ {
+ _delegateSelectorsCache |= _CPTableViewHeightOfRowSelector;
+ _hasVariableHeightRows = YES;
+ }
+ else
+ _hasVariableHeightRows = NO;
+}
+
+
/*
Tells the table view that the number of rows in the table
has changed.
@@ -505,6 +611,12 @@
}
}
+- (void)noteHeightOfRowsWithIndexesChanged:(CPIndexSet)indexSet
+{
+ // FIXME: more efficient version is possible since we know which indexes changes
+ [self _recalculateColumnHeight];
+}
+
/*
Returns the rectangle bounding the specified row.
@param aRowIndex the row to obtain a rectangle for
@@ -512,7 +624,7 @@
*/
- (CGRect)rectOfRow:(int)aRowIndex
{
- return CPRectMake(0.0, aRowIndex * (_rowHeight + _intercellSpacing.height), CPRectGetWidth([self bounds]), _rowHeight);
+ return CPRectMake(0.0, ROW_MIN_Y(aRowIndex), CPRectGetWidth([self bounds]), ROW_HEIGHT(aRowIndex));
}
/*
@@ -539,6 +651,13 @@
if (_hasVariableHeightRows)
{
+ _rowMinYs[0] = 0;
+ for (var row = 0; row < _numberOfRows; row++)
+ {
+ _rowHeights[row] = [_delegate tableView:self heightOfRow:row];
+ _rowMinYs[row+1] = _rowMinYs[row] + _rowHeights[row] + _intercellSpacing.height;
+ }
+ _columnHeight = _rowMinYs[_numberOfRows]; // last index is one more than last row, and is the total column height
}
else
_columnHeight = _numberOfRows * (_rowHeight + _intercellSpacing.height);
@@ -575,7 +694,9 @@
{
[self _recalculateColumnHeight];
[self setFrameSize:CGSizeMake(CGRectGetWidth([self frame]), [self _columnHeight])];
- }
+ }
+
+ _objectValueCache = [];
[self setNeedsDisplay:YES];
}
@@ -583,22 +704,12 @@
- (void)viewWillDraw
{
[self loadTableCellsInRect:[self visibleRectInParent]];
-
- //alert("oh yes. " + CPStringFromRect([self visibleRect]));
- //[self reloadData];
}
- (void)drawRect:(CGRect)aRect
{
}
-- (void)setFrameSize:(CGSize)aFrameSize
-{
- [super setFrameSize:aFrameSize];
-
-// [self setNeedsDisplay:YES];
-}
-
- (void)displaySoon
{
// window.setTimeout();
@@ -613,7 +724,6 @@
selector:@selector(viewBoundsChanged:)
name:CPViewBoundsDidChangeNotification
object:[[self enclosingScrollView] contentView]];
- //console.warn("cheese");
}
- (void)viewBoundsChanged:(CPNotification)aNotification
@@ -623,4 +733,490 @@
[self setNeedsDisplay:YES];
}
+/*
+- (void)setAllowsColumnReordering:(BOOL)allowsColumnReordering
+{
+ if (_allowsColumnReordering === _allowsColumnReordering)
+ return;
+
+ _allowsColumnReordering = allowsColumnReordering;
+}
+- (void)allowsColumnReordering
+{
+ return _allowsColumnReordering;
+}
+
+- (void)setAllowsColumnResizing:(BOOL)allowsColumnResizing
+{
+ if (_allowsColumnResizing === allowsColumnResizing)
+ return;
+
+ _allowsColumnResizing = allowsColumnResizing;
+}
+- (void)allowsColumnResizing
+{
+ return _allowsColumnResizing;
+}
+
+- (void)setAllowsColumnSelection:(BOOL)allowsColumnSelection
+{
+ if (_allowsColumnSelection === allowsColumnSelection)
+ return;
+
+ _allowsColumnSelection = allowsColumnSelection;
+}
+- (void)allowsColumnSelection
+{
+ return _allowsColumnSelection;
+}
+*/
+
+- (void)setAllowsMultipleSelection:(BOOL)allowsMultipleSelection
+{
+ if (_allowsMultipleSelection === allowsMultipleSelection)
+ return;
+
+ _allowsMultipleSelection = allowsMultipleSelection;
+
+ // TODO: more stuff?
+}
+- (void)allowsMultipleSelection
+{
+ return _allowsMultipleSelection;
+}
+
+- (void)setAllowsEmptySelection:(BOOL)allowsEmptySelection
+{
+ if (_allowsEmptySelection === allowsEmptySelection)
+ return;
+
+ _allowsEmptySelection = allowsEmptySelection;
+}
+- (void)allowsEmptySelection
+{
+ return _allowsEmptySelection;
+}
+
+
+/*
+ Returns the index of the row at the given point, or CPNotFound (-1) if it is out of range.
+ @param aPoint the point
+ @return the index of the row at aPoint
+*/
+- (int)rowAtPoint:(CGPoint)aPoint
+{
+ var index = [self _rowAtY:aPoint.y]
+
+ if (index >= 0 && index < _numberOfRows)
+ return index;
+ else
+ return CPNotFound;
+}
+
+- (int)columnAtPoint:(CGPoint)aPoint
+{
+ var index = [self _columnAtY:aPoint.x]
+
+ if (index >= 0 && index < _numberOfColumns)
+ return index;
+ else
+ return CPNotFound;
+}
+
+/*
+ @ignore
+
+ Internal version takes a Y value, returns an index, or -1 if its beyond the min, or numberOfRows if it's beyond the max
+*/
+- (int)_rowAtY:(float)y
+{
+ if (_hasVariableHeightRows)
+ {
+ var a = 0,
+ b = _numberOfRows;
+
+ if (y < _rowMinYs[0])
+ return -1;
+ if (y >= _rowMinYs[_rowMinYs.length-1])
+ return _numberOfRows;
+
+ // binary search
+ while (true)
+ {
+ var half = a + Math.floor((b - a) / 2);
+
+ if (half === _numberOfRows - 1)
+ return _numberOfRows - 1;
+
+ if (y >= _rowMinYs[half+1])
+ a = half;
+ else if (y < _rowMinYs[half])
+ b = half;
+ else
+ return half;
+ }
+ }
+ else
+ return FLOOR(y / (_rowHeight + _intercellSpacing.height));
+}
+
+/*
+ @ignore
+
+ Internal version takes a X value, returns an index, or -1 if its beyond the min, or numberOfColumns if it's beyond the max
+*/
+- (int)_columnAtX:(float)y
+{
+ var a = 0,
+ b = _numberOfColumns;
+
+ var last = [_tableColumnViews[_numberOfColumns-1] frame];
+ if (y < [_tableColumnViews[0] frame].origin.x)
+ return -1;
+ if (y >= last.origin.x + last.size.width)
+ return _numberOfColumns;
+
+ // binary search
+ while (true)
+ {
+ var half = a + Math.floor((b - a) / 2);
+
+ if (half === _numberOfColumns - 1)
+ return _numberOfColumns - 1;
+
+ if (y >= [_tableColumnViews[half+1] frame].origin.x)
+ a = half;
+ else if (y < [_tableColumnViews[half] frame].origin.x)
+ b = half;
+ else
+ return half;
+ }
+}
+
+/*
+ Selects the specified row indexes, optionally adding to existing selection
+ @param indexes the indexes to select
+ @param extend whether or not to add to the existing selection
+*/
+- (void)selectRowIndexes:(CPIndexSet)indexes byExtendingSelection:(BOOL)extend
+{
+ // FIXME: should this be subject to the delegate filters, etc?
+
+ if (extend)
+ _selectedRowIndexes = [[_selectedRowIndexes copy] addIndexes:indexes];
+ else if ([indexes count] > 0 || _allowsEmptySelection)
+ _selectedRowIndexes = [indexes copy];
+
+ [self _drawSelection];
+}
+
+/*
+ Returns a CPIndexSet of the selected rows
+ @return indexes of the selected rows
+*/
+- (CPIndexSet)selectedRowIndexes
+{
+ return _selectedRowIndexes;
+}
+
+/*
+ Returns the number of selected rows
+ @return number of selected rows
+*/
+- (int)numberOfSelectedRows
+{
+ return [_selectedRowIndexes count];
+}
+
+
+/*
+ Deselects all rows if allowsEmptySelection is true. If delegate responds to "selectionShouldChangeInTableView:", asks if it should chnage.
+ Sends the CPTableViewSelectionDidChangeNotification on deselection.
+ @param the sender in a target/action
+*/
+- (void)deselectAll:(id)sender
+{
+ if (!_allowsEmptySelection || [_selectedRowIndexes count] === 0 ||
+ ((_delegateSelectorsCache & _CPTableViewSelectionShouldChangeSelector) && ![_delegate selectionShouldChangeInTableView:self]))
+ return;
+
+ [self selectRowIndexes:[CPIndexSet indexSet] byExtendingSelection:NO];
+ [[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil];
+}
+
+- (void)editColumn:(int)columnIndex row:(int)rowIndex withEvent:(CPEvent)theEvent select:(BOOL)flag
+{
+
+}
+
+/*
+ @ignore
+*/
+- (void)_updateSelectionWithMouseAtRow:(int)aRow
+{
+ // Make a preliminary new selection
+ var newSelection;
+ if (_allowsMultipleSelection)
+ newSelection = [CPIndexSet indexSetWithIndexesInRange:CPMakeRange(MIN(aRow, _selectionStartRow), ABS(aRow-_selectionStartRow)+1)];
+ else if (aRow >= 0 && aRow < _numberOfRows)
+ newSelection = [CPIndexSet indexSetWithIndex:aRow];
+ else
+ newSelection = [CPIndexSet indexSet];
+
+ // If cmd/ctrl was held down XOR the old selection with the proposed selection
+ if (_allowsMultipleSelection && _selectionModifier & (CPCommandKeyMask | CPControlKeyMask | CPAlternateKeyMask))
+ {
+ // A = newSelection, B = _previousSelectedRowIndexes
+ // (A intersection B) = (A - (A - B))
+ var intersection = [newSelection copy],
+ difference = [newSelection copy];
+ [difference removeIndexes:_previousSelectedRowIndexes];
+ [intersection removeIndexes:difference]
+
+ // (A xor B) = (A + B) - (A intersection B)
+ [newSelection addIndexes:_previousSelectedRowIndexes];
+ [newSelection removeIndexes:intersection];
+
+ // FIXME: if multiple selection is off, and we cmd/ctrl click the previously selected row, then deselect it.
+ }
+
+ // if the new selection is different than the old selection
+ if (![newSelection isEqualToIndexSet:_selectedRowIndexes])
+ {
+ // ask the delegate if we should change the selection
+ if ((_delegateSelectorsCache & _CPTableViewSelectionShouldChangeSelector) && ![_delegate selectionShouldChangeInTableView:self])
+ return;
+
+ // ask the delegate which indexes can be selected. selectionIndexesForProposedSelection is faster than shouldSelectRow
+ if (_delegateSelectorsCache & _CPTableViewSelectionIndexesForProposedSelectionSelector)
+ newSelection = [_delegate tableView:self selectionIndexesForProposedSelection:newSelection];
+ else if (_delegateSelectorsCache & _CPTableViewShouldSelectRowSelector)
+ {
+ var indexes = [];
+ [newSelection getIndexes:indexes maxCount:Number.MAX_VALUE inIndexRange:nil];
+ for (var i = 0; i < indexes.length; i++)
+ if (![_delegate tableView:self shouldSelectRow:indexes[i]])
+ [newSelection removeIndex:indexes[i]];
+ }
+ }
+
+ // if empty selection is not allowed and the new selection has nothing selected, abort
+ if (!_allowsEmptySelection && [newSelection count] === 0)
+ return;
+
+ // if the new selection is *still* different, and update the selection and send a notification
+ if (![newSelection isEqualToIndexSet:_selectedRowIndexes])
+ {
+ [self selectRowIndexes:newSelection byExtendingSelection:NO];
+ [[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewSelectionIsChangingNotification object:self userInfo:nil];
+ }
+}
+
+/*
+ @ignore
+*/
+- (void)mouseDown:(CPEvent)anEvent
+{
+ [self trackSelection:anEvent];
+}
+
+/*
+ @ignore
+*/
+- (void)trackSelection:(CPEvent)anEvent
+{
+ var type = [anEvent type],
+ point = [self convertPoint:[anEvent locationInWindow] fromView:nil],
+ currentRow = MAX(0, MIN(_numberOfRows-1, [self _rowAtY:point.y]));
+
+ if (type == CPLeftMouseUp)
+ {
+ if ([anEvent clickCount] === 2)
+ {
+ CPLog.warn("edit?!");
+ }
+ else if (![_previousSelectedRowIndexes isEqualToIndexSet:_selectedRowIndexes])
+ {
+ [[CPNotificationCenter defaultCenter] postNotificationName:CPTableViewSelectionDidChangeNotification object:self userInfo:nil];
+ }
+
+ return;
+ }
+
+ if (type == CPLeftMouseDown)
+ {
+ _previousSelectedRowIndexes = _selectedRowIndexes;
+ _selectionModifier = [anEvent modifierFlags];
+
+ if (_selectionModifier & CPShiftKeyMask)
+ _selectionStartRow = (ABS([_previousSelectedRowIndexes firstIndex] - currentRow) < ABS([_previousSelectedRowIndexes lastIndex] - currentRow)) ?
+ [_previousSelectedRowIndexes firstIndex] : [_previousSelectedRowIndexes lastIndex];
+ else
+ _selectionStartRow = currentRow;
+
+ [self _updateSelectionWithMouseAtRow:currentRow];
+ }
+ else if (type == CPLeftMouseDragged)
+ {
+ [self _updateSelectionWithMouseAtRow:currentRow];
+ }
+
+ [CPApp setTarget:self selector:@selector(trackSelection:) forNextEventMatchingMask:CPLeftMouseDraggedMask | CPLeftMouseUpMask untilDate:nil inMode:nil dequeue:YES];
+}
+
+/*
+ @ignore
+*/
+- (void)_drawSelection
+{
+ if (!_currentlySelected) {
+ _currentlySelected = [CPIndexSet indexSet];
+ _selectionViews = [];
+ _selectionViewsPool = [];
+ }
+
+ // TODO: we could also remove selections that aren't visible, but then we'll need to run this on every scroll/resize?
+
+ // get array of indexes we can remove
+ var removeSet = [_currentlySelected copy],
+ indexesToRemove = [];
+ [removeSet removeIndexes:_selectedRowIndexes];
+ [removeSet getIndexes:indexesToRemove maxCount:Number.MAX_VALUE inIndexRange:nil];
+
+ // get array of indexes we need to add
+ var addSet = [_selectedRowIndexes copy],
+ indexesToAdd = [];
+ [addSet removeIndexes:_currentlySelected];
+ [addSet getIndexes:indexesToAdd maxCount:Number.MAX_VALUE inIndexRange:nil];
+
+ for (var i = 0; i < indexesToRemove.length; i++)
+ {
+ var row = indexesToRemove[i];
+ for (var column = 0; column < _numberOfColumns; column++)
+ if ([_tableCells[column][row] respondsToSelector:@selector(highlight:)])
+ [_tableCells[column][row] highlight:NO];
+ }
+ for (var i = 0; i < indexesToAdd.length; i++)
+ {
+ var row = indexesToAdd[i];
+ for (var column = 0; column < _numberOfColumns; column++)
+ if ([_tableCells[column][row] respondsToSelector:@selector(highlight:)])
+ [_tableCells[column][row] highlight:YES];
+ }
+
+ // add each one we need to add, taking the selection views from removed seelctions, the pool, or new
+ for (var i = 0; i < indexesToAdd.length; i++)
+ {
+ var index = indexesToAdd[i],
+ view;
+
+ if (indexesToRemove.length > 0)
+ {
+ view = _selectionViews[indexesToRemove.pop()];
+ }
+ else if (_selectionViewsPool.length > 0)
+ {
+ view = _selectionViewsPool.pop();
+ [self addSubview:view positioned:CPWindowBelow relativeTo:nil];
+ }
+ else
+ {
+ view = [[CPView alloc] init];
+ [view setBackgroundColor:[CPColor alternateSelectedControlColor]];
+
+ [self addSubview:view positioned:CPWindowBelow relativeTo:nil];
+ }
+
+ _selectionViews[index] = view;
+
+ var frame = [self rectOfRow:index];
+ frame.size.height += _intercellSpacing.height - 1;
+ //frame.size.width += 500;
+
+ [view setFrame:frame];
+ }
+
+ // remove any selections that weren't already reused
+ for (var i = 0; i < indexesToRemove.length; i++)
+ {
+ var row = indexesToRemove[i],
+ view = _selectionViews[row];
+
+ [view removeFromSuperview];
+ _selectionViewsPool.push(view);
+ }
+
+ // update the currently selected index set
+ _currentlySelected = [_selectedRowIndexes copy];
+}
+
@end
+
+
+var CPTableViewDataSourceKey = @"CPTableViewDataSourceKey",
+ CPTableViewDelegateKey = @"CPTableViewDelegateKey",
+ CPTableViewHeaderViewKey = @"CPTableViewHeaderViewKey",
+ CPTableViewTableColumnsKey = @"CPTableViewTableColumnsKey",
+ CPTableViewRowHeightKey = @"CPTableViewRowHeightKey",
+ CPTableViewIntercellSpacingKey = @"CPTableViewIntercellSpacingKey",
+ CPTableViewMultipleSelectionKey = @"CPTableViewMultipleSelectionKey",
+ CPTableViewEmptySelectionKey = @"CPTableViewEmptySelectionKey";
+
+@implementation CPTableView (CPCoding)
+
+- (id)initWithCoder:(CPCoder)aCoder
+{
+ if (self = [super initWithCoder:aCoder])
+ {
+ [self _init];
+
+ _dataSource = [aCoder decodeObjectForKey:CPTableViewDataSourceKey];
+ _delegate = [aCoder decodeObjectForKey:CPTableViewDelegateKey];
+
+ _rowHeight = [aCoder decodeFloatForKey:CPTableViewRowHeightKey];
+ _intercellSpacing = [aCoder decodeSizeForKey:CPTableViewIntercellSpacingKey];
+
+ _allowsMultipleSelection = [aCoder decodeBoolForKey:CPTableViewMultipleSelectionKey];
+ _allowsEmptySelection = [aCoder decodeBoolForKey:CPTableViewEmptySelectionKey];
+
+ var tableColumns = [aCoder decodeObjectForKey:CPTableViewTableColumnsKey];
+ for (var i = 0; i < tableColumns.length; i++)
+ [self addTableColumn:tableColumns[i]];
+ }
+
+ return self;
+}
+
+- (void)encodeWithCoder:(CPCoder)aCoder
+{
+ [super encodeWithCoder:aCoder];
+
+ [aCoder encodeObject:_dataSource forKey:CPTableViewDataSourceKey];
+ [aCoder encodeObject:_delegate forKey:CPTableViewDelegateKey];
+
+ [aCoder encodeObject:_tableColumns forKey:CPTableViewTableColumnsKey];
+
+ [aCoder encodeFloat:_rowHeight forKey:CPTableViewRowHeightKey];
+ [aCoder encodeSize:_intercellSpacing forKey:CPTableViewIntercellSpacingKey];
+
+ [aCoder encodeBool:_allowsMultipleSelection forKey:CPTableViewMultipleSelectionKey];
+ [aCoder encodeBool:_allowsEmptySelection forKey:CPTableViewEmptySelectionKey];
+}
+
+@end
+
+
+
+@implementation CPColor (TableView)
+
++ (CPColor)alternateSelectedControlColor
+{
+ return [[CPColor alloc] _initWithRGBA:[0.22, 0.46, 0.84, 1.0]];
+}
+
++ (CPColor)secondarySelectedControlColor
+{
+ return [[CPColor alloc] _initWithRGBA:[0.83, 0.83, 0.83, 1.0]];
+}
+
+@end
\ No newline at end of file
diff --git a/Tools/nib2cib/NSAppKit.j b/Tools/nib2cib/NSAppKit.j
index 3e6c3df86..a0e6de2e7 100644
--- a/Tools/nib2cib/NSAppKit.j
+++ b/Tools/nib2cib/NSAppKit.j
@@ -43,6 +43,8 @@
@import "NSSegmentedControl.j"
@import "NSSlider.j"
@import "NSSplitView.j"
+@import "NSTableColumn.j"
+@import "NSTableView.j"
@import "NSTabView.j"
@import "NSTabViewItem.j"
@import "NSTextField.j"
diff --git a/Tools/nib2cib/NSTableColumn.j b/Tools/nib2cib/NSTableColumn.j
new file mode 100644
index 000000000..b92d90ef6
--- /dev/null
+++ b/Tools/nib2cib/NSTableColumn.j
@@ -0,0 +1,71 @@
+/*
+ * NSTableColumn.j
+ * nib2cib
+ *
+ * Created by Thomas Robinson.
+ * Copyright 2008, 280 North, Inc.
+ *
+ * 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-1301 USA
+ */
+
+
+@import
+
+@implementation CPTableColumn (NSCoding)
+
+- (id)NS_initWithCoder:(CPCoder)aCoder
+{
+ self = [self init];
+
+ if (self)
+ {
+ _identifier = [aCoder decodeObjectForKey:@"NSIdentifier"];
+
+ var template = [[CPTableColumn alloc] ]
+
+ //var dataViewCell = [aCoder decodeObjectForKey:@"NSDataCell"];
+
+ _dataView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
+ [_dataView setValue:[CPColor whiteColor] forThemedAttributeName:"text-color" inControlState:CPControlStateHighlighted];
+
+ //_headerView = [aCoder decodeObjectForKey:@"NSHeaderCell"];
+ _headerView = [[CPTextField alloc] initWithFrame:CPRectMakeZero()];
+
+ _width = [aCoder decodeFloatForKey:@"NSWidth"];
+ _minWidth = [aCoder decodeFloatForKey:@"NSMinWidth"];
+ _maxWidth = [aCoder decodeFloatForKey:@"NSMaxWidth"];
+
+ _resizingMask = [aCoder decodeBoolForKey:@"NSIsResizable"];
+ }
+
+ return self;
+}
+
+@end
+
+@implementation NSTableColumn : CPTableColumn
+{
+}
+
+- (id)initWithCoder:(CPCoder)aCoder
+{
+ return [self NS_initWithCoder:aCoder];
+}
+
+- (Class)classForKeyedArchiver
+{
+ return [CPTableColumn class];
+}
+
diff --git a/Tools/nib2cib/NSTableView.j b/Tools/nib2cib/NSTableView.j
new file mode 100644
index 000000000..b6fa36ad2
--- /dev/null
+++ b/Tools/nib2cib/NSTableView.j
@@ -0,0 +1,73 @@
+/*
+ * NSTableView.j
+ * nib2cib
+ *
+ * Created by Thomas Robinson.
+ * Copyright 2008, 280 North, Inc.
+ *
+ * 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-1301 USA
+ */
+
+
+@import
+
+@implementation CPTableView (NSCoding)
+
+- (id)NS_initWithCoder:(CPCoder)aCoder
+{
+ self = [super NS_initWithCoder:aCoder];
+
+ if (self)
+ {
+ var flags = [aCoder decodeIntForKey:@"NSTvFlags"];
+
+ //_dataSource = [aCoder decodeObjectForKey:CPTableViewDataSourceKey];
+ //_delegate = [aCoder decodeObjectForKey:CPTableViewDelegateKey];
+
+ //_headerView = [aCoder decodeObjectForKey:@"NSHeaderView"];
+ //[_headerView setTableView:self];
+
+ //_cornerView = [aCoder decodeObjectForKey:@"NSCornerView"];
+
+ _tableColumns = [aCoder decodeObjectForKey:@"NSTableColumns"];
+ [_tableColumns makeObjectsPerformSelector:@selector(setTableView:) withObject:self];
+
+ _rowHeight = [aCoder decodeFloatForKey:@"NSRowHeight"];
+ _intercellSpacing = CGSizeMake([aCoder decodeFloatForKey:"NSIntercellSpacingWidth"], [aCoder decodeFloatForKey:"NSIntercellSpacingHeight"]);
+
+ _allowsMultipleSelection = (flags & 0x08000000) ? YES : NO;
+ _allowsEmptySelection = (flags & 0x10000000) ? YES : NO;
+ }
+
+ return self;
+}
+
+@end
+
+@implementation NSTableView : CPTableView
+{
+}
+
+- (id)initWithCoder:(CPCoder)aCoder
+{
+ return [self NS_initWithCoder:aCoder];
+}
+
+- (Class)classForKeyedArchiver
+{
+ return [CPTableView class];
+}
+
+@end
diff --git a/Tools/nib2cib/NSWindowTemplate.j b/Tools/nib2cib/NSWindowTemplate.j
index 5c4343ac5..90945ce8e 100644
--- a/Tools/nib2cib/NSWindowTemplate.j
+++ b/Tools/nib2cib/NSWindowTemplate.j
@@ -71,6 +71,9 @@ var NSBorderlessWindowMask = 0x00,
(_windowStyleMask & NSResizableWindowMask ? CPResizableWindowMask : 0) |
(_windowStyleMask & NSTexturedBackgroundWindowMask ? NSTexturedBackgroundWindowMask : 0) |
(_windowStyleMask & NSHUDBackgroundWindowMask ? CPHUDBackgroundWindowMask : 0);
+
+ if ([aCoder decodeObjectForKey:"NSFrameAutosaveName"] === "CPBorderlessBridgeWindowMask")
+ _windowStyleMask = CPBorderlessBridgeWindowMask;
/*if (![_windowClass isEqualToString:@"NSPanel"])
_windowRect.origin.y -= [NSMainMenuView menuHeight]; // compensation for the additional menu bar