• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSTableColumn subclass and custom binding (solution!)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSTableColumn subclass and custom binding (solution!)


  • Subject: Re: NSTableColumn subclass and custom binding (solution!)
  • From: Alexander Lamb <email@hidden>
  • Date: Tue, 29 Aug 2006 07:12:15 +0200

Hello,

Ok, maybe not the best solution, but here is an "hybrid" of bindings and "classical way" to solve the problem.

1)
I have a subclass of NSButtonCell which responds to color (to draw a color background)


2)
I have a subclass of NSTableColumn to handle the additionnal binding: color


First, in IB, I set the subclass for my column as well as the subclass for the table cell (subclass of NSButtonCell). I also use IB for the other bindings (value in this case)

In my app controller, I do a simple binding with my custom table column:

[theTableColumn bind:@"color" toObject:theArrayController withKeyPath:@"arrangedObjects.color" options:nil];

Now, here is the code in my NSTableColumn subclass:

- (void)bind:(NSString *)bindingName toObject:(id) observableController withKeyPath:(NSString *)keyPath options: (NSDictionary *)options
{
if([bindingName isEqualToString:@"color"])
{
// before binding, initialise the observedObjects to an empty array...
observedObjects = [[NSMutableArray alloc] init];
arrayController = [observableController retain];
[observableController addObserver:self forKeyPath:keyPath options:nil context:ControllerObservationContext];
}
else
[super bind:bindingName toObject:observableController withKeyPath:keyPath options:options];
}


As you can see, I keep a NSMutableArray of observed objects as well as a reference to the NSArrayController. I also call super, which means I don't interfere with the other bindings.

Now, for some reason, I also need to implement accessor methods for color, but they do nothing:

- (void)setColor:(NSArray *)values
	{
	}

- (NSArray *)color
	{
	return nil;
	}

Now, the implementation of the "observe..."

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id) object change:(NSDictionary *)change context:(void *)context
{
if(context == ColorsObservationContext)
{
NSTableView *tableView = [self tableView];
[tableView setNeedsDisplayInRect:[tableView frameOfCellAtColumn: [tableView columnWithIdentifier:[self identifier]] row: [[arrayController arrangedObjects] indexOfObject:object]]];
}
else if(context == ControllerObservationContext)
{
// here, we know object is an NSArrayController... so lets compare the arranged objects with the observed objects
NSArray *arrangedObjects = [object arrangedObjects];
// First the ones which were removed...
NSEnumerator *enumerator = [observedObjects objectEnumerator];
id anObject;
while(anObject = [enumerator nextObject])
{
if([arrangedObjects indexOfObject:anObject] == NSNotFound)
{
[anObject removeObserver:self];
[observedObjects removeObject:anObject];
}
}
// Then, the new ones...
enumerator = [arrangedObjects objectEnumerator];
while(anObject = [enumerator nextObject])
{
if([observedObjects indexOfObject:anObject] == NSNotFound)
{
[observedObjects addObject:anObject];
[anObject addObserver:self forKeyPath:@"color" options:nil context:ColorsObservationContext];
}
}
}
}


If I am observing the array controller changes, I am simply adding or removing observing for the color attribute for the individual objects in the array.
If I am observing an individual color change, I need to tell the table view containing my column to redraw a given cell. I know which row by using the arranged objects in the arrayController I kept as a reference.


Now, I need to give the correct color for the cell. Since table columns reuse the same cell, it has to be done at the last moment, so I implement the following method in my table column subclass:

- dataCellForRow:(int)row
{
LSColorCheckCell *cell = [self dataCell];
if(row >= 0)
{
[cell setColor:[[[arrayController arrangedObjects] objectAtIndex:row] color]];
}
return cell;
}


And.... it works:-)

However, it still seems "bricolé" (french way of saying "not very elegantly built"). I would love to know how the Cocoa classes implement this for the basic bindings.

Any  improvements suggestions are welcome!

Alex
--
Alexander Lamb
email@hidden


_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
  • Prev by Date: Re: Links in NSTextField
  • Next by Date: endian problems with UTF16 on Intel Macs
  • Previous by thread: NSTextInput protocol problem
  • Next by thread: endian problems with UTF16 on Intel Macs
  • Index(es):
    • Date
    • Thread