PDA

View Full Version : Trying to draw custom selection on NSTableView subclass




chris-morrison
Oct 29, 2010, 07:33 AM
Hi all,

I am implementing my own subclass of NSTableView which has a gradient selection marker like iTunes or iMovie.

I have got all my subclasses set up and I have prepared the image for the selection marker, but I have hit a maddening brick wall.

I am using the following code to draw my custom selection in my NSTableView subclass.

- (void)highlightSelectionInClipRect:(NSRect)clipRect
{
if ([self selectedRow] == -1) return;

if (__useDarkProLook)
{
[self lockFocus];

NSImage *selImage = [NSImage imageNamed:@"TableViewSelection.tiff"];
[selImage setFlipped:[self isFlipped]];
NSIndexSet *selectedRowIndexes = [self selectedRowIndexes];
NSInteger currentIndex = [selectedRowIndexes firstIndex];

while (currentIndex != NSNotFound)
{
NSRect rowRect = [self rectOfRow:currentIndex];

if (!NSIsEmptyRect(rowRect))
{
NSLog(@"Drawing selection for %llu (%f, %f, %f, %f)", currentIndex, rowRect.origin.x, rowRect.origin.y, rowRect.size.width, rowRect.size.height);

[selImage drawInRect:rowRect fromRect:rowRect operation:NSCompositeSourceOver fraction:1.0];
}

currentIndex = [selectedRowIndexes indexGreaterThanIndex:currentIndex];
}

[self unlockFocus];
}

[super highlightSelectionInClipRect:clipRect];
}

- (id)_highlightColorForCell:(NSCell *)cell;
{
if (__useDarkProLook) return nil;

return [super _highlightColorForCell:cell];
}

When I load some data into my table view and click on the first item my selection is drawn perfectly.

However, when I click on any of the other items nothing happens apart from a slight change of the color of the text. I can only seem to draw the selection on the first item.

I have tried absolutely everything and I cannot get past this stumbling block.

Has anyone else experienced this or have any idea what I have missed?

Regards,

Chris



jared_kipe
Oct 29, 2010, 08:13 AM
First off, set a breakpoint or put in an NSLog to see if your method is getting called every time you select a row. Perhaps selectedRow isn't changing?

chris-morrison
Oct 29, 2010, 09:29 AM
There is an NSLog before the line to draw the image, the method is being called (with the correct index).

Below is the output to the console in Xcode when I click on eight items in the table view one after the other.

2010-10-29 15:23:44.179 MyApp[30065:5703] Drawing selection for 0 (0.000000, 0.000000, 418.000000, 20.000000)
2010-10-29 15:23:46.419 MyApp[30065:5703] Drawing selection for 1 (0.000000, 20.000000, 418.000000, 20.000000)
2010-10-29 15:23:47.843 MyApp[30065:5b07] Drawing selection for 2 (0.000000, 40.000000, 418.000000, 20.000000)
2010-10-29 15:23:49.099 MyApp[30065:5b07] Drawing selection for 3 (0.000000, 60.000000, 418.000000, 20.000000)
2010-10-29 15:23:50.275 MyApp[30065:5b07] Drawing selection for 4 (0.000000, 80.000000, 418.000000, 20.000000)
2010-10-29 15:23:52.331 MyApp[30065:5b07] Drawing selection for 5 (0.000000, 100.000000, 418.000000, 20.000000)
2010-10-29 15:23:53.459 MyApp[30065:5703] Drawing selection for 6 (0.000000, 120.000000, 418.000000, 20.000000)
2010-10-29 15:23:54.299 MyApp[30065:5b07] Drawing selection for 7 (0.000000, 140.000000, 418.000000, 20.000000)

robbieduncan
Oct 29, 2010, 09:33 AM
What is the clip rect you are being passed? Have you considered the possibility that you should not be working out the row position, rather you should just fill the supplied rect with the highlight image and the table view will deal with it being in the correct place on screen?

Edit: it appears that I'm wrong on that...

Bernard SG
Oct 29, 2010, 10:34 AM
Clear your view at the start of your "While" loop?

chris-morrison
Oct 29, 2010, 11:15 AM
Clear your view at the start of your "While" loop?

Could you elaborate a bit on that on that please.

jared_kipe
Oct 29, 2010, 12:17 PM
Does it work properly the FIRST time you click it (as in any row) or just the First row?? Does it deselect properly?

chris-morrison
Oct 29, 2010, 12:59 PM
Does it work properly the FIRST time you click it (as in any row) or just the First row?? Does it deselect properly?

It selects and deselects correctly however many times you click on the very first row only.

chown33
Oct 29, 2010, 01:23 PM
Did you read any code samples before writing your code?
If so, what URLs?

Did you pattern your code after a specific example?
Which one?

If none of the above, consider looking up some examples.


What does your code draw after highlightSelectionInClipRect: has returned?
The ref doc says "This method is invoked before drawRow:clipRect:." so post any override of that, and post the delegate's cell-drawing code.

Logically, if something is drawn after highlightSelectionInClipRect returns, then that drawn content will appear instead of anything drawn by highlightSelectionInClipRect.

Sydde
Oct 29, 2010, 01:43 PM
Look here:
[selImage drawInRect:rowRect fromRect:rowRect operation:NSCompositeSourceOver fraction:1.0];

hint: try NSZeroRect

chris-morrison
Oct 29, 2010, 01:48 PM
I have been scouring the net for examples on how to do this.

Here is some of the code on which mine is loosely based.

http://blog.wilshipley.com/2005_07_01_archive.html
http://github.com/omnigroup/omnigroup/blob/5582216948ade7dcc79e23fe0cfbc837d322c1de/Frameworks/OmniAppKit/Widgets.subproj/OAGradientTableView.m

chris-morrison
Oct 29, 2010, 01:52 PM
Look here:
[selImage drawInRect:rowRect fromRect:rowRect operation:NSCompositeSourceOver fraction:1.0];

hint: try NSZeroRect

That seems to have done the trick. Thank you.

jared_kipe
Oct 29, 2010, 01:56 PM
Look here:
[selImage drawInRect:rowRect fromRect:rowRect operation:NSCompositeSourceOver fraction:1.0];

hint: try NSZeroRect

Good one, it's trying to draw part of the image that isn't there (in the image coordinate space)

However, I'm not sure you intend to draw the whole image. Maybe something like

maybe make a new rect with (0.0, 0.0, rowRect.size.width, rowRect.size.height)

Sydde
Oct 29, 2010, 02:18 PM
However, I'm not sure you intend to draw the whole image.

He did say "gradient", so I guessed it was a stretchable tiny image (or ought to be). But your point is well taken: chris-morrison would be well advised to read the docs for NSImage so that he understands what the fix did.

jared_kipe
Oct 29, 2010, 02:46 PM
He did say "gradient", so I guessed it was a stretchable tiny image (or ought to be). But your point is well taken: chris-morrison would be well advised to read the docs for NSImage so that he understands what the fix did.

I didn't notice, I was coming from the POV that it was working for the first bar, so the smaller change would be to ask the image to display the size that it was originally displaying (and apparently working).

chris-morrison
Oct 29, 2010, 06:30 PM
I have studied the NSImage docs with a bit more acumen and it is now clear what was going wrong.

We live and learn.

Thank you everyone for your help.

Chris