mirror of
https://github.com/darlinghq/darling-cocotron.git
synced 2025-02-07 20:58:00 +00:00
+ Johannes Fortmann's patch:
- table view editing - fine-grained bindings for table columns - NSArray objectsAtIndexes: - some fixes for KVO + Rolf Jansen's NSSortDescriptor initWithCoder/encodeWithCoder + Rolf Jansen's NSCell/NSButtonCell controlSize patch
This commit is contained in:
parent
c21384fbed
commit
e346fd856b
@ -579,12 +579,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
NSGraphicsStyle should probably do this adjustment too
|
||||
*/
|
||||
if((_bezelStyle==NSRoundedBezelStyle) && (_highlightsBy&NSPushInCellMask) && (_highlightsBy&NSChangeGrayCellMask) && (_showsStateBy==NSNoCellMask)){
|
||||
if(![self isKindOfClass:[NSPopUpButtonCell class]]){
|
||||
frame.size.height-=10;
|
||||
frame.origin.y+=[control isFlipped]?-5:5;
|
||||
frame.size.width-=6;
|
||||
frame.origin.x+=3;
|
||||
}
|
||||
if (![self isKindOfClass:[NSPopUpButtonCell class]] && _controlSize <= NSSmallControlSize)
|
||||
{
|
||||
frame.size.width -= 10 - _controlSize*2;
|
||||
frame.size.height -= 10 - _controlSize*2;
|
||||
frame.origin.x += 5 - _controlSize;
|
||||
frame.origin.y += [control isFlipped] ? _controlSize*2 - 3 : 7 - _controlSize*2;
|
||||
}
|
||||
}
|
||||
|
||||
if(_bezelStyle==NSDisclosureBezelStyle){
|
||||
|
@ -75,9 +75,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
check=[keyed decodeObjectForKey:@"NSSupport"];
|
||||
if([check isKindOfClass:[NSFont class]])
|
||||
_font=[check retain];
|
||||
|
||||
if(_font==nil)
|
||||
_font=[[NSFont userFontOfSize:0] retain]; // ?
|
||||
|
||||
_controlSize=(flags2&0xE0000)>>17;
|
||||
if (_font==nil)
|
||||
_font=[[NSFont userFontOfSize:13 - _controlSize*2] retain];
|
||||
}
|
||||
else {
|
||||
_state=[coder decodeIntForKey:@"NSCell state"];
|
||||
@ -551,6 +552,9 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
- (void)setControlSize:(NSControlSize)size {
|
||||
_controlSize = size;
|
||||
[_font release];
|
||||
_font = [[NSFont userFontOfSize:13 - _controlSize*2] retain];
|
||||
[(NSControl *)[self controlView] updateCell:self];
|
||||
}
|
||||
|
||||
-(void)takeObjectValueFrom:sender {
|
||||
|
@ -28,6 +28,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
id filterPredicate;
|
||||
id _selection;
|
||||
id arrangedObjects;
|
||||
|
||||
}
|
||||
|
||||
-(NSArray *)sortDescriptors;
|
||||
@ -86,4 +87,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
//-(NSArray *)arrangeObjects:(NSArray *)objects;
|
||||
//-(void)rearrangeObjects;
|
||||
|
||||
// private
|
||||
-(void)_selectionMayHaveChanged;
|
||||
|
||||
@end
|
||||
|
@ -15,6 +15,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
#import <Foundation/NSPredicate.h>
|
||||
#import <Foundation/NSKeyValueObserving.h>
|
||||
|
||||
@interface NSArrayController(forwardRefs)
|
||||
-(void)_selectionMayHaveChanged;
|
||||
- (void)setArrangedObjects:(id)value;
|
||||
@end
|
||||
|
||||
@implementation NSArrayController
|
||||
|
||||
+(void)initialize
|
||||
@ -23,7 +28,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
triggerChangeNotificationsForDependentKey:@"selection"];
|
||||
}
|
||||
|
||||
-(id)initWithCoder:(id)coder
|
||||
-(id)initWithCoder:(NSCoder*)coder
|
||||
{
|
||||
self=[super init];
|
||||
if(self)
|
||||
@ -38,8 +43,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
id declaredKeys=[coder decodeObjectForKey:@"NSDeclaredKeys"];
|
||||
}
|
||||
// FIX: cocotron nib loading seems not to retain top-level objects. _dirtiest_ possible hack: retain
|
||||
return [self retain];
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
@ -51,24 +55,21 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
}
|
||||
|
||||
-(id)awakeFromNib
|
||||
{
|
||||
[self _selectionMayHaveChanged];
|
||||
}
|
||||
|
||||
-(void)_selectionMayHaveChanged
|
||||
{
|
||||
[self willChangeValueForKey:@"selection"];
|
||||
_selection=[[NSArrayControllerSelectionProxy alloc] initWithArrayController:self];
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
[self didChangeValueForKey:@"selection"];
|
||||
}
|
||||
|
||||
- (id)contentArray {
|
||||
return [[contentArray retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setArrangedObjects:(id)value {
|
||||
if (arrangedObjects != value)
|
||||
{
|
||||
[arrangedObjects release];
|
||||
arrangedObjects = [[NSArray alloc] initWithArray:value];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setContentArray:(id)value {
|
||||
if (contentArray != value) {
|
||||
[contentArray release];
|
||||
@ -82,6 +83,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setArrangedObjects:(id)value {
|
||||
if (arrangedObjects != value)
|
||||
{
|
||||
[arrangedObjects release];
|
||||
arrangedObjects = [value copy];
|
||||
}
|
||||
}
|
||||
|
||||
-(id)arrangedObjects
|
||||
{
|
||||
return arrangedObjects;
|
||||
@ -195,6 +204,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
[self setSelectionIndexes:idxs];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -83,7 +83,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(void)setValue:(id)value forKey:(NSString *)key
|
||||
{
|
||||
NSLog(@"setValue %@ forKey %@", value, key);
|
||||
[[controller selectedObjects] setValue:value forKey:key];
|
||||
}
|
||||
|
||||
|
@ -7,13 +7,14 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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 <Foundation/NSObject.h>
|
||||
|
||||
@class NSString;
|
||||
|
||||
@interface _NSBinder : NSObject {
|
||||
id source;
|
||||
id destination;
|
||||
id keyPath;
|
||||
id bindingPath;
|
||||
id binding;
|
||||
NSString* keyPath;
|
||||
NSString* bindingPath;
|
||||
NSString* binding;
|
||||
id options;
|
||||
}
|
||||
- (id)options;
|
||||
@ -25,11 +26,11 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
- (id)destination;
|
||||
- (void)setDestination:(id)value;
|
||||
|
||||
- (id)keyPath;
|
||||
- (void)setKeyPath:(id)value;
|
||||
- (NSString*)keyPath;
|
||||
- (void)setKeyPath:(NSString*)value;
|
||||
|
||||
- (id)binding;
|
||||
- (void)setBinding:(id)value;
|
||||
- (NSString*)binding;
|
||||
- (void)setBinding:(NSString*)value;
|
||||
|
||||
-(void)bind;
|
||||
-(void)unbind;
|
||||
|
@ -7,6 +7,7 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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 "NSBinder.h"
|
||||
#import <AppKit/NSObject+BindingSupport.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
@implementation _NSBinder
|
||||
|
||||
@ -35,22 +36,22 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
}
|
||||
}
|
||||
|
||||
- (id)keyPath {
|
||||
- (NSString*)keyPath {
|
||||
return [[keyPath retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setKeyPath:(id)value {
|
||||
- (void)setKeyPath:(NSString*)value {
|
||||
if (keyPath != value) {
|
||||
[keyPath release];
|
||||
keyPath = [value copy];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)binding {
|
||||
- (NSString*)binding {
|
||||
return [[binding retain] autorelease];
|
||||
}
|
||||
|
||||
- (void)setBinding:(id)value {
|
||||
- (void)setBinding:(NSString*)value {
|
||||
if (binding != value) {
|
||||
[binding release];
|
||||
binding = [value copy];
|
||||
|
@ -15,7 +15,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
@implementation _NSKVOBinder
|
||||
-(void)startObservingChanges
|
||||
{
|
||||
NSLog(@"binding between %@.%@ alias %@ and %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
//NSLog(@"binding between %@.%@ alias %@ and %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
|
||||
[source addObserver:self
|
||||
forKeyPath:bindingPath
|
||||
@ -60,14 +60,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
if(object==source)
|
||||
{
|
||||
NSLog(@"bind event from %@.%@ alias %@ to %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
//NSLog(@"bind event from %@.%@ alias %@ to %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
|
||||
[destination setValue:[change valueForKey:NSKeyValueChangeNewKey]
|
||||
forKeyPath:keyPath];
|
||||
}
|
||||
else if(object==destination)
|
||||
{
|
||||
NSLog(@"bind event from %@.%@ to %@.%@ alias %@ (%@)", [destination className], keyPath, [source className], binding, bindingPath, self);
|
||||
//NSLog(@"bind event from %@.%@ to %@.%@ alias %@ (%@)", [destination className], keyPath, [source className], binding, bindingPath, self);
|
||||
|
||||
[source setValue:[change valueForKey:NSKeyValueChangeNewKey]
|
||||
forKeyPath:bindingPath];
|
||||
|
@ -22,4 +22,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
-(id)_replacementKeyPathForBinding:(id)binding;
|
||||
-(void)_cleanupBinders;
|
||||
-(NSArray*)_allUsedBinders;
|
||||
-(id)_binderForBinding:(id)binding create:(BOOL)create;
|
||||
-(id)_binderForBinding:(id)binding;
|
||||
@end
|
||||
|
@ -20,6 +20,11 @@ NSMutableDictionary *bindersForObjects=nil;
|
||||
return [_NSKVOBinder class];
|
||||
}
|
||||
|
||||
-(id)_binderForBinding:(id)binding;
|
||||
{
|
||||
return [self _binderForBinding:binding create:NO];
|
||||
}
|
||||
|
||||
-(id)_binderForBinding:(id)binding create:(BOOL)create
|
||||
{
|
||||
if(!bindersForObjects)
|
||||
|
@ -7,15 +7,20 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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 "NSBinder.h"
|
||||
|
||||
@class NSArray;
|
||||
@class NSMutableArray;
|
||||
|
||||
@interface _NSTableColumnBinder : _NSBinder
|
||||
{
|
||||
NSArray* rowValues;
|
||||
id pathToArray;
|
||||
NSMutableArray* rowValues;
|
||||
NSString* arrayKeyPath;
|
||||
NSString* valueKeyPath;
|
||||
}
|
||||
-(void)applyToCell:(id)cell inRow:(int)row;
|
||||
-(void)applyFromCell:(id)cell inRow:(int)row;
|
||||
-(void)updateRowValues;
|
||||
-(NSMutableArray*)rowValues;
|
||||
-(BOOL)allowsEditingForRow:(int)row;
|
||||
-(void)cacheArrayKeyPath;
|
||||
@end
|
||||
|
||||
|
||||
|
@ -14,10 +14,12 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
#import <Foundation/NSString.h>
|
||||
#import <AppKit/NSTableView.h>
|
||||
#import <AppKit/NSTableColumn.h>
|
||||
#import <AppKit/NSArrayController.h>
|
||||
#import <AppKit/NSObject+BindingSupport.h>
|
||||
|
||||
|
||||
@implementation _NSTableColumnBinder
|
||||
- (NSArray *)rowValues
|
||||
- (NSMutableArray *)rowValues
|
||||
{
|
||||
return [[rowValues retain] autorelease];
|
||||
}
|
||||
@ -34,32 +36,72 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(void)applyToCell:(id)cell inRow:(int)row
|
||||
{
|
||||
[cell setValue:[rowValues objectAtIndex:row] forKey:bindingPath];
|
||||
if(!arrayKeyPath)
|
||||
[self cacheArrayKeyPath];
|
||||
[cell setValue:[[rowValues objectAtIndex:row] valueForKey:valueKeyPath] forKey:bindingPath];
|
||||
}
|
||||
|
||||
-(void)applyFromCell:(id)cell inRow:(int)row
|
||||
{
|
||||
[[rowValues objectAtIndex:row] setValue:[cell valueForKeyPath:bindingPath]
|
||||
forKeyPath:valueKeyPath];
|
||||
}
|
||||
|
||||
-(void)cacheArrayKeyPath
|
||||
{
|
||||
// find content binding
|
||||
id tableViewContentBinder=[[source tableView] _binderForBinding:@"content"];
|
||||
if(!tableViewContentBinder)
|
||||
return;
|
||||
|
||||
// this should be something like "arrangedObjects"
|
||||
arrayKeyPath=[[tableViewContentBinder keyPath] copy];
|
||||
|
||||
if(![keyPath hasPrefix:arrayKeyPath])
|
||||
[NSException raise:NSInvalidArgumentException
|
||||
format:@"content binding %@ of table view %@ doesn't fit value binding %@ on column %@",
|
||||
arrayKeyPath,
|
||||
[source tableView],
|
||||
keyPath,
|
||||
source];
|
||||
|
||||
// get rest of key path ("value" from "arrangedObjects.value")
|
||||
valueKeyPath=[[keyPath substringFromIndex:[arrayKeyPath length]+1] retain];
|
||||
}
|
||||
|
||||
-(BOOL)allowsEditingForRow:(int)row
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[arrayKeyPath release];
|
||||
[valueKeyPath release];
|
||||
[self setRowValues:nil];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void)startObservingChanges
|
||||
{
|
||||
//NSLog(@"%@: observing path %@ on %@", [self className], keyPath, destination);
|
||||
NS_DURING
|
||||
|
||||
//[destination addObserver:self forKeyPath:keyPath options:0 context:destination];
|
||||
[destination addObserver:self forKeyPath:arrayKeyPath options:0 context:destination];
|
||||
[rowValues addObserver:self
|
||||
toObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [rowValues count])]
|
||||
forKeyPath:valueKeyPath
|
||||
options:0
|
||||
context:nil];
|
||||
NS_HANDLER
|
||||
NS_ENDHANDLER
|
||||
|
||||
}
|
||||
|
||||
-(void)stopObservingChanges
|
||||
{
|
||||
NS_DURING
|
||||
// [destination removeObserver:self forKeyPath:keyPath];
|
||||
[destination removeObserver:self forKeyPath:arrayKeyPath];
|
||||
[rowValues removeObserver:self
|
||||
fromObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [rowValues count])]
|
||||
forKeyPath:valueKeyPath];
|
||||
NS_HANDLER
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
@ -71,15 +113,15 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)kp ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
[self stopObservingChanges];
|
||||
|
||||
if(object==source)
|
||||
{
|
||||
NSLog(@"bind event from %@.%@ alias %@ to %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
}
|
||||
//NSLog(@"bind event from %@.%@ alias %@ to %@.%@ (%@)", [source className], binding, bindingPath, [destination className], keyPath, self);
|
||||
}
|
||||
else if(context==destination)
|
||||
{
|
||||
NSLog(@"bind event from %@.%@ to %@.%@ alias %@ (%@)", [destination className], keyPath, [source className], binding, bindingPath, self);
|
||||
[self stopObservingChanges];
|
||||
|
||||
//NSLog(@"bind event from %@.%@ to %@.%@ alias %@ (%@)", [destination className], keyPath, [source className], binding, bindingPath, self);
|
||||
|
||||
[self updateRowValues];
|
||||
|
||||
@ -87,17 +129,45 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
[source reloadData];
|
||||
if([source respondsToSelector:@selector(tableView)])
|
||||
[[source tableView] reloadData];
|
||||
|
||||
[self startObservingChanges];
|
||||
}
|
||||
|
||||
else if(context==nil)
|
||||
{
|
||||
if([source respondsToSelector:@selector(reloadData)])
|
||||
[source reloadData];
|
||||
if([source respondsToSelector:@selector(tableView)])
|
||||
[[source tableView] reloadData];
|
||||
|
||||
if([destination respondsToSelector:@selector(_selectionMayHaveChanged)])
|
||||
[destination _selectionMayHaveChanged];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
-(void)finishBind
|
||||
{
|
||||
[self cacheArrayKeyPath];
|
||||
|
||||
[self syncUp];
|
||||
[self startObservingChanges];
|
||||
}
|
||||
|
||||
-(void)bind
|
||||
{
|
||||
[self syncUp];
|
||||
[self startObservingChanges];
|
||||
[self cacheArrayKeyPath];
|
||||
|
||||
// At the time of binding, the binders for the table view may not yet be initialized.
|
||||
// In that case, we cannot determine which part of our key path is the array and
|
||||
// which is the value key. In that case, we defer the finishing steps.
|
||||
if(!arrayKeyPath)
|
||||
[self performSelector:@selector(finishBind) withObject:nil afterDelay:0.0];
|
||||
else
|
||||
[self finishBind];
|
||||
}
|
||||
|
||||
|
||||
|
||||
-(void)unbind
|
||||
{
|
||||
[self stopObservingChanges];
|
||||
@ -110,20 +180,18 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(id)objectAtIndex:(unsigned)row
|
||||
{
|
||||
return [rowValues objectAtIndex:row];
|
||||
return [[rowValues objectAtIndex:row] valueForKey:valueKeyPath];
|
||||
}
|
||||
|
||||
-(id)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ %@", [super description], [self rowValues]];
|
||||
|
||||
}
|
||||
|
||||
-(void)updateRowValues
|
||||
{
|
||||
[self setRowValues:[destination valueForKeyPath:keyPath]];
|
||||
[self setRowValues:[destination valueForKeyPath:arrayKeyPath]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -154,7 +222,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
{
|
||||
[source performSelector:@selector(reloadData)
|
||||
withObject:nil
|
||||
afterDelay:1.0];
|
||||
afterDelay:0.0];
|
||||
[source reloadData];
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
[_headerView setTableView:self];
|
||||
_cornerView=[[keyed decodeObjectForKey:@"NSCornerView"] retain];
|
||||
_tableColumns=[[NSMutableArray alloc] initWithArray:[keyed decodeObjectForKey:@"NSTableColumns"]];
|
||||
[_tableColumns makeObjectsPerformSelector:@selector(setTableView:) withObject:self];
|
||||
_backgroundColor=[[keyed decodeObjectForKey:@"NSBackgroundColor"] retain];
|
||||
_gridColor=[[keyed decodeObjectForKey:@"NSGridColor"] retain];
|
||||
_rowHeight=[keyed decodeFloatForKey:@"NSRowHeight"];
|
||||
@ -501,11 +502,13 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
// also.. i wonder if remove should use an isEqual method in NSTableColumn, or removeObjectIdenticalTo...
|
||||
-(void)addTableColumn:(NSTableColumn *)column {
|
||||
[_tableColumns addObject:column];
|
||||
[column setTableView:self];
|
||||
[self reloadData];
|
||||
[_headerView setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
-(void)removeTableColumn:(NSTableColumn *)column {
|
||||
[column setTableView:nil];
|
||||
[_tableColumns removeObject:column];
|
||||
[self reloadData];
|
||||
[_headerView setNeedsDisplay:YES];
|
||||
@ -538,9 +541,9 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
if ([self delegateShouldEditTableColumn:editingColumn row:row] == NO)
|
||||
return;
|
||||
|
||||
if ([self dataSourceCanSetObjectValue] == NO)
|
||||
if ([self dataSourceCanSetObjectValue] == NO && [[editingColumn _binderForBinding:@"value" create:NO] allowsEditingForRow:row] == NO)
|
||||
[NSException raise:NSInternalInconsistencyException
|
||||
format:@"data source does not respond to tableView:setObjectValue:forTableColumn:row:"];
|
||||
format:@"data source does not respond to tableView:setObjectValue:forTableColumn:row: and binding is read-only"];
|
||||
|
||||
_editedColumn = column;
|
||||
_editedRow = row;
|
||||
@ -552,6 +555,8 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
[_editingCell setBordered:YES];
|
||||
[(NSCell *)_editingCell setObjectValue:[self dataSourceObjectValueForTableColumn:editingColumn row:row]];
|
||||
|
||||
[editingColumn prepareCell:_editingCell inRow:row];
|
||||
|
||||
_currentEditor=[[self window] fieldEditor:YES forObject:self];
|
||||
_currentEditor=[_editingCell setUpFieldEditorAttributes:_currentEditor];
|
||||
[_currentEditor retain];
|
||||
@ -624,9 +629,7 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
}
|
||||
|
||||
-(void)selectRow:(int)row byExtendingSelection:(BOOL)extend {
|
||||
NSLog(@"selectRow:%i extend:%i", row, extend);
|
||||
|
||||
// selecting a row deselects all columns
|
||||
// selecting a row deselects all columns
|
||||
[_selectedColumns removeAllObjects];
|
||||
|
||||
NSMutableIndexSet* selectedRowIndexes=[[[self selectedRowIndexes] mutableCopy] autorelease];
|
||||
@ -929,7 +932,16 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
// avoid possible row synch issues
|
||||
_numberOfRows = [self numberOfRows];
|
||||
if (_editedRow >= 0 && _editedRow < _numberOfRows)
|
||||
[self dataSourceSetObjectValue:[_editingCell objectValue] forTableColumn:editedColumn row:_editedRow];
|
||||
{
|
||||
if([self dataSourceCanSetObjectValue])
|
||||
{
|
||||
[self dataSourceSetObjectValue:[_editingCell objectValue] forTableColumn:editedColumn row:_editedRow];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[editedColumn _binderForBinding:@"value" create:NO] applyFromCell:_editingCell inRow:_editedRow];
|
||||
}
|
||||
}
|
||||
|
||||
[self abortEditing];
|
||||
|
||||
@ -1146,7 +1158,9 @@ NSString *NSTableViewColumnDidResizeNotification=@"NSTableViewColumnDidResizeNot
|
||||
}
|
||||
else if ([event clickCount] == 2) {
|
||||
// nb this logic was backwards previously
|
||||
if ([self dataSourceCanSetObjectValue]) {
|
||||
id binder=[[_tableColumns objectAtIndex:_clickedColumn] _binderForBinding:@"value" create:NO];
|
||||
if ([self dataSourceCanSetObjectValue] ||
|
||||
[binder allowsEditingForRow:_clickedRow]) {
|
||||
if (_clickedColumn != NSNotFound && _clickedRow != NSNotFound)
|
||||
[self editColumn:[self clickedColumn] row:_clickedRow withEvent:event select:YES];
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
#import <Foundation/NSArray.h>
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSSet.h>
|
||||
#import <Foundation/NSDebug.h>
|
||||
#import "NSNibKeyedUnarchiver.h"
|
||||
#import "NSCustomObject.h"
|
||||
#import <AppKit/NSNibConnector.h>
|
||||
@ -113,7 +114,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
NS_DURING
|
||||
[[_connections objectAtIndex:i] establishConnection];
|
||||
NS_HANDLER
|
||||
// NSLog(@"Exception during -establishConnection %@",localException);
|
||||
if(NSDebugEnabled)
|
||||
NSLog(@"Exception during -establishConnection %@",localException);
|
||||
NS_ENDHANDLER
|
||||
}
|
||||
}
|
||||
|
@ -212,19 +212,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
objects[i]=[self objectAtIndex:loc+i];
|
||||
}
|
||||
|
||||
-(NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
|
||||
unsigned i,count=[indexes count];
|
||||
unsigned buffer[count];
|
||||
id objects[count];
|
||||
|
||||
count=[indexes getIndexes:buffer maxCount:count inIndexRange:NULL];
|
||||
// getObjects:range: would make more sense
|
||||
for(i=0;i<count;i++)
|
||||
objects[i]=[self objectAtIndex:buffer[i]];
|
||||
|
||||
return [NSArray arrayWithObjects:objects count:count];
|
||||
}
|
||||
|
||||
-(NSArray *)subarrayWithRange:(NSRange)range {
|
||||
if(NSMaxRange(range)>[self count])
|
||||
NSRaiseException(NSRangeException,self,_cmd,@"range %@ beyond count %d",
|
||||
@ -451,6 +438,32 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
return result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// untested
|
||||
-(NSArray *)objectsAtIndexes:(NSIndexSet *)indexes {
|
||||
unsigned i,count=[indexes count];
|
||||
unsigned buffer[count];
|
||||
id objects[count];
|
||||
|
||||
count=[indexes getIndexes:buffer maxCount:count inIndexRange:NULL];
|
||||
// getObjects:range: would make more sense
|
||||
for(i=0;i<count;i++)
|
||||
objects[i]=[self objectAtIndex:buffer[i]];
|
||||
|
||||
return [NSArray arrayWithObjects:objects count:count];
|
||||
}
|
||||
#endif
|
||||
|
||||
-(NSArray *)objectsAtIndexes:(NSIndexSet*)indexes
|
||||
{
|
||||
unsigned idx=[indexes firstIndex];
|
||||
id ret=[NSMutableArray array];
|
||||
while(idx!=NSNotFound)
|
||||
{
|
||||
[ret addObject:[self objectAtIndex:idx]];
|
||||
idx=[indexes indexGreaterThanIndex:idx];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@end
|
||||
|
||||
|
@ -138,8 +138,10 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
replace(proxyObject, replaceSel, index, anObject);
|
||||
else
|
||||
{
|
||||
[self removeObjectAtIndex:index];
|
||||
[self insertObject:anObject atIndex:index];
|
||||
id target=[[self _representedObject] mutableCopy];
|
||||
[target replaceObjectAtIndex:index withObject:anObject];
|
||||
[self _setRepresentedObject:target];
|
||||
[target release];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,4 +32,5 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
-(void)setNilValueForKey:(id)key;
|
||||
|
||||
-(id)mutableArrayValueForKey:(id)key;
|
||||
-(id)mutableArrayValueForKeyPath:(id)keyPath;
|
||||
@end
|
||||
|
@ -180,6 +180,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
|
||||
-(id)valueForKey:(NSString*)key
|
||||
{
|
||||
if(!key)
|
||||
return [self valueForUndefinedKey:nil];
|
||||
SEL sel=NSSelectorFromString(key);
|
||||
// FIXME: getKey, _getKey, isKey, _isKey are missing
|
||||
|
||||
@ -367,6 +369,16 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
{
|
||||
return [[[NSKVCMutableArray alloc] initWithKey:key forProxyObject:self] autorelease];
|
||||
}
|
||||
|
||||
-(id)mutableArrayValueForKeyPath:(id)keyPath
|
||||
{
|
||||
NSString* firstPart, *rest;
|
||||
[keyPath _KVC_partBeforeDot:&firstPart afterDot:&rest];
|
||||
if(rest)
|
||||
return [[self valueForKeyPath:firstPart] valueForKeyPath:rest];
|
||||
else
|
||||
return [[[NSKVCMutableArray alloc] initWithKey:firstPart forProxyObject:self] autorelease];
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
@ -7,7 +7,8 @@ The above copyright notice and this permission notice shall be included in all c
|
||||
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 <Foundation/NSObject.h>
|
||||
@class NSDictionary,NSArray;
|
||||
#import <Foundation/NSArray.h>
|
||||
@class NSDictionary;
|
||||
|
||||
FOUNDATION_EXPORT NSString *const NSKeyValueChangeKindKey;
|
||||
FOUNDATION_EXPORT NSString *const NSKeyValueChangeNewKey;
|
||||
@ -34,6 +35,13 @@ typedef unsigned int NSKeyValueObservingOptions;
|
||||
-(void*)observationInfo;
|
||||
@end
|
||||
|
||||
@interface NSArray(KeyValueObserving)
|
||||
-(void)addObserver:(NSObject *)observer toObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
|
||||
-(void)removeObserver:(NSObject *)observer fromObjectsAtIndexes:(NSIndexSet *)indexes forKeyPath:(NSString *)keyPath;
|
||||
-(void)addObserver:(id)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context;
|
||||
-(void)removeObserver:(id)observer forKeyPath:(NSString*)keyPath;
|
||||
@end
|
||||
|
||||
@protocol NSKeyValueObserver
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
|
||||
@end
|
||||
|
@ -10,6 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
#import <Foundation/NSString.h>
|
||||
#import <Foundation/NSKeyValueCoding.h>
|
||||
#import <Foundation/NSRaise.h>
|
||||
#import <Foundation/NSCoder.h>
|
||||
#import <Foundation/NSKeyedUnarchiver.h>
|
||||
|
||||
@implementation NSSortDescriptor
|
||||
|
||||
@ -29,15 +31,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-initWithCoder:(NSCoder *)coder {
|
||||
NSUnimplementedMethod();
|
||||
return self;
|
||||
}
|
||||
|
||||
-(void)encodeWithCoder:(NSCoder *)coder {
|
||||
NSUnimplementedMethod();
|
||||
}
|
||||
|
||||
-copyWithZone:(NSZone *)zone {
|
||||
return [self retain];
|
||||
}
|
||||
@ -68,4 +61,40 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
return [[[isa alloc] initWithKey:_key ascending:!_ascending selector:_selector] autorelease];
|
||||
}
|
||||
|
||||
// NSCoding protocol
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
if ([coder allowsKeyedCoding])
|
||||
{
|
||||
[coder encodeObject:_key forKey:@"Key"];
|
||||
[coder encodeBool:_ascending forKey:@"Ascending"];
|
||||
[coder encodeObject:NSStringFromSelector(_selector) forKey: @"Selector"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[coder encodeObject:_key];
|
||||
[coder encodeValueOfObjCType:@encode(BOOL) at:&_ascending];
|
||||
[coder encodeObject:NSStringFromSelector(_selector)];
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)coder {
|
||||
if ([coder isKindOfClass:[NSKeyedUnarchiver class]])
|
||||
{
|
||||
NSKeyedUnarchiver *keyed = (NSKeyedUnarchiver *)coder;
|
||||
_key = [[keyed decodeObjectForKey:@"Key"] copy];
|
||||
_ascending = [keyed decodeBoolForKey:@"Ascending"];
|
||||
_selector = NSSelectorFromString([keyed decodeObjectForKey:@"Selector"]);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
_key = [[coder decodeObject] copy];
|
||||
[coder decodeValueOfObjCType:@encode(BOOL) at:&_ascending];
|
||||
_selector = NSSelectorFromString([coder decodeObject]);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
x
Reference in New Issue
Block a user