Re: Sizing table columns to fit data - a solution looking for suggestions

2009-01-30 Thread Corbin Dunn


On Jan 30, 2009, at 8:33 AM, Steve Cronin wrote:


Corbin;

Hey thanks for replying!

First off, don't use the 'tableView:' prefix for your own delegate  
methods. Consider what would happen if AppKit introduced the same  
delegate method in a future release. Well, I can tell you from  
experience that it won't be good. So, please make it something like  
"scTableView:...".


This method is an existing method provided by NSObject from Apple!   
I didn't make the name up, I used an already existing delegate  
mechanism.

Am I not understanding your point?


Hah! No -- that was totally an error on my part; I thought you were  
making up your own delegate method...I didn't read the name carefully  
enough. Sorry about that mistake!





Use CGFloat not float.


OK, but why?


For 64-bit compatibility. You can read up on CGFloat / NSInteger for  
more info.




Setting the width in a loop is not good for performance; it might  
cause the table to relayout a lot of times.


The code you cited is NOT inside a loop!?? Or am I not understanding  
how something works?


No; your right here too; I wasn't reading it closely enough...




 NSCell *cell = [tableView preparedCellAtRow:i column:column];


10.5 Only -- I wanted a 10.4 compatible solution.  I didn't say that  
and I should have.


Ah, that's a bummer :)

That means you have to use float instead of CGFloat.

corbin


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Sizing table columns to fit data - a solution looking for suggestions

2009-01-30 Thread Steve Cronin

Corbin;

Hey thanks for replying!

First off, don't use the 'tableView:' prefix for your own delegate  
methods. Consider what would happen if AppKit introduced the same  
delegate method in a future release. Well, I can tell you from  
experience that it won't be good. So, please make it something like  
"scTableView:...".


This method is an existing method provided by NSObject from Apple!  I  
didn't make the name up, I used an already existing delegate mechanism.

Am I not understanding your point?


Use CGFloat not float.


OK, but why?

Setting the width in a loop is not good for performance; it might  
cause the table to relayout a lot of times.


The code you cited is NOT inside a loop!?? Or am I not understanding  
how something works?



  NSCell *cell = [tableView preparedCellAtRow:i column:column];


10.5 Only -- I wanted a 10.4 compatible solution.  I didn't say that  
and I should have.


Thanks,
Steve



On Jan 30, 2009, at 10:10 AM, Corbin Dunn wrote:

Below is a reasonably generic Cocoa solution for implementing this  
behavior.
The tableView I developed this for uses an arrayController with  
individual column bindings; not the old school -dataSource methods  
for handling the data.

This code should exist in tableView's delegate.
This solution handles both strings and images.
I don't like the reliance on calling the arrayController directly  
but for now it serves my purpose


Overall, I would do it slightly differently; I would subclass  
NSTAbleHeaderView, figure out what column needs it to be autoresized  
and when (ie: double click), and then ask the delegate (optionally)  
what size it wants. But, I would make a default implementation based  
on -cellSize (possibly doing a monte carlo simulation on the number  
of rows, if there were a lot of rows, to help with performance).


Here are comments on your version:



I am interested in both criticisms and improvements - both will  
serve the Cocoa community..


- (void)tableView:(NSTableView *)tableView  
mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn {	





NSEvent *event = [NSApp currentEvent];
if ([event clickCount]==2) {
NSPoint location = [event locationInWindow];
NSTableHeaderView *header = [tableView headerView]; 
location = [header convertPoint:location fromView:nil];
		if (location.x>=2.0) location.x-=2;  // offset point 2 pixels  
'cause the 'split' cursor is a little 'permissive'
		NSTableColumn *thisColumn = [[tableView tableColumns]  
objectAtIndex:[header columnAtPoint:location]];

NSString *maxStr = @"";
id thisObj;
NSCell *dCell;
float newWidth, maxStringWidth =  0.0 ,maxImageWidth = 0.0;


Use CGFloat not float.


// me don't like the next line
		NSArray *theValues = [[myArrayController arrangedObjects]  
valueForKey:[thisColumn identifier]];  //dump the tableColumn  
values to an array



Instead of this hardcoded access, do this (sorry, not complete, but  
you should understand the idea):


CGFloat maxWidth = 0;
for (NSInteger i = 0; i < tableView.numberOfRows; i++) {
  NSCell *cell = [tableView preparedCellAtRow:i column:column];
  NSSize size = [cell cellSize];
  if (size.width > maxWidth) maxWidth = size.width;
}
[tableColumn setWidth:maxWidth];

The code above is *much* more generic. Note that it doesn't consider  
the indentation for outlineviews.


if ([thisColumn width] != newWidth) {
[thisColumn setWidth:newWidth];


Setting the width in a loop is not good for performance; it might  
cause the table to relayout a lot of times.


Anyways, as usual, it never hurts to log feature requests for AppKit  
to do this for you.


corbin


} else {
	//if already max then here double-click sets to half max!   
(maybe NOT do this if images were found?)

[thisColumn setWidth:newWidth/2.0];
}
}
}




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Sizing table columns to fit data - a solution looking for suggestions

2009-01-30 Thread Corbin Dunn
Below is a reasonably generic Cocoa solution for implementing this  
behavior.
The tableView I developed this for uses an arrayController with  
individual column bindings; not the old school -dataSource methods  
for handling the data.

This code should exist in tableView's delegate.
This solution handles both strings and images.
I don't like the reliance on calling the arrayController directly  
but for now it serves my purpose


Overall, I would do it slightly differently; I would subclass  
NSTAbleHeaderView, figure out what column needs it to be autoresized  
and when (ie: double click), and then ask the delegate (optionally)  
what size it wants. But, I would make a default implementation based  
on -cellSize (possibly doing a monte carlo simulation on the number of  
rows, if there were a lot of rows, to help with performance).


Here are comments on your version:



I am interested in both criticisms and improvements - both will  
serve the Cocoa community..


- (void)tableView:(NSTableView *)tableView  
mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn {	


First off, don't use the 'tableView:' prefix for your own delegate  
methods. Consider what would happen if AppKit introduced the same  
delegate method in a future release. Well, I can tell you from  
experience that it won't be good. So, please make it something like  
"scTableView:...".




NSEvent *event = [NSApp currentEvent];
if ([event clickCount]==2) {
NSPoint location = [event locationInWindow];
NSTableHeaderView *header = [tableView headerView]; 
location = [header convertPoint:location fromView:nil];
		if (location.x>=2.0) location.x-=2;  // offset point 2 pixels  
'cause the 'split' cursor is a little 'permissive'
		NSTableColumn *thisColumn = [[tableView tableColumns]  
objectAtIndex:[header columnAtPoint:location]];

NSString *maxStr = @"";
id thisObj;
NSCell *dCell;
float newWidth, maxStringWidth =  0.0 ,maxImageWidth = 0.0;


Use CGFloat not float.


// me don't like the next line
		NSArray *theValues = [[myArrayController arrangedObjects]  
valueForKey:[thisColumn identifier]];  //dump the tableColumn values  
to an array



Instead of this hardcoded access, do this (sorry, not complete, but  
you should understand the idea):


CGFloat maxWidth = 0;
for (NSInteger i = 0; i < tableView.numberOfRows; i++) {
   NSCell *cell = [tableView preparedCellAtRow:i column:column];
   NSSize size = [cell cellSize];
   if (size.width > maxWidth) maxWidth = size.width;
}
[tableColumn setWidth:maxWidth];

The code above is *much* more generic. Note that it doesn't consider  
the indentation for outlineviews.


if ([thisColumn width] != newWidth) {
[thisColumn setWidth:newWidth];


Setting the width in a loop is not good for performance; it might  
cause the table to relayout a lot of times.


Anyways, as usual, it never hurts to log feature requests for AppKit  
to do this for you.


corbin


} else {
	//if already max then here double-click sets to half max!   
(maybe NOT do this if images were found?)

[thisColumn setWidth:newWidth/2.0];
}
}
}


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Sizing table columns to fit data - a solution looking for suggestions

2009-01-29 Thread Steve Cronin

Folks;

iTunes and Excel both have a feature wherein if you double-click on  
the column divider in the tableHeader then the table column width is  
adjusted to the maximum width of the data in the column.


Below is a reasonably generic Cocoa solution for implementing this  
behavior.
The tableView I developed this for uses an arrayController with  
individual column bindings; not the old school -dataSource methods for  
handling the data.

This code should exist in tableView's delegate.
This solution handles both strings and images.
I don't like the reliance on calling the arrayController directly but  
for now it serves my purpose


I am interested in both criticisms and improvements - both will serve  
the Cocoa community..


- (void)tableView:(NSTableView *)tableView  
mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn {	

NSEvent *event = [NSApp currentEvent];
if ([event clickCount]==2) {
NSPoint location = [event locationInWindow];
NSTableHeaderView *header = [tableView headerView]; 
location = [header convertPoint:location fromView:nil];
		if (location.x>=2.0) location.x-=2;  // offset point 2 pixels 'cause  
the 'split' cursor is a little 'permissive'
		NSTableColumn *thisColumn = [[tableView tableColumns] objectAtIndex: 
[header columnAtPoint:location]];

NSString *maxStr = @"";
id thisObj;
NSCell *dCell;
float newWidth, maxStringWidth =  0.0 ,maxImageWidth = 0.0;
// me don't like the next line
		NSArray *theValues = [[myArrayController arrangedObjects]  
valueForKey:[thisColumn identifier]];  //dump the tableColumn values  
to an array

if ((theValues!=nil) && ([theValues count]>0)) {
NSEnumerator *valEnum = [theValues objectEnumerator];
// find the longest string or widest image
while ((thisObj = [valEnum nextObject]) != nil) {
if ([thisObj isKindOfClass:[NSString class]]) {
	if ([thisObj length] > [maxStr length]) maxStr = thisObj;   // 
keep the string 'cause later we use dataCell to get -width

} else if ([thisObj isKindOfClass:[NSImage 
class]]) {
	if ([thisObj size].width > maxImageWidth) maxImageWidth =  
[thisObj size].width;

}
}
			//below covers the case where a mix of strings and images were  
found - chooses the wider of the two

if ([maxStr length]> 0) {
dCell = [thisColumn dataCell];
[dCell setStringValue:maxStr];
maxStringWidth = [dCell cellSize].width;
}
			newWidth = (maxStringWidth > maxImageWidth) ? maxStringWidth :  
maxImageWidth;
			//this check prevents anything from happing unless we have found  
something actionable

if (newWidth>0) {
//bump up max if necessary
if (newWidth>[thisColumn maxWidth]) [thisColumn  
setMaxWidth:newWidth];

//set width to max if not already max
if ([thisColumn width] != newWidth) {
[thisColumn setWidth:newWidth];
} else {
	//if already max then here double-click sets to half max!  (maybe  
NOT do this if images were found?)

[thisColumn setWidth:newWidth/2.0];
}
}
}
}
}

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com