Skip to content

cocoa

NSTableView, NSArrayController and Bindings : smart resizing columns

Après recherche, impossible de trouver le moyen facile de demander à un NSTableView de redimensionner intelligemment ses NSTableColumn de manière à ce que leur taille soit la même que si l’on double-cliquait directement sur la bordure à droite de la colonne.

Etant donné que les méthodes divergent en fonction des manières d’alimenter le NSTableView (via un dataSource, ou via les Cocoa Bindings sur les NSTableColumn), je précise qu’ici il s’agit de ce dernier cas, avec un NSArrayController.

Voici donc une Category pour NSTableView, il s’agit d’une V1, il lui manque notamment les points suivants :

  • Elargir proportionnellement les colonnes avec l’espace libre
  • Appeller si nécessaire setMinWidth et/ou setMaxWidth sur les colonnes

Mais cela vous apportera un point de départ ; le header :

//  NSTableView+autoColumnSizingForBindingWithNSArrayController.h
//  extramol
//  Created by David CHANIAL on 04/08/12.

#import <Cocoa/Cocoa.h>

@interface NSTableView (autoColumnSizingForBindingWithNSArrayController)
- (void)autoColumnSizingForBindingWithNSArrayController;
@end

Et pour l’implémentation :

//  NSTableView+autoColumnSizingForBindingWithNSArrayController.m
//  extramol
//  Created by David CHANIAL on 04/08/12.

#import "NSTableView+autoColumnSizingForBindingWithNSArrayController.h"

@implementation NSTableView (autoColumnSizingForBindingWithNSArrayController)

- (void)autoColumnSizingForBindingWithNSArrayController {
    NSArray *tableColumns = [self tableColumns];

    for (NSTableColumn *column in tableColumns){
        // init
        NSDictionary *bindingInformations = [column infoForBinding:@"value"];
        if(bindingInformations == nil) continue;
        id observedObject = [bindingInformations valueForKey:NSObservedObjectKey];
        if(observedObject == nil) continue;
        // Get Array
        NSArray *items = [observedObject valueForKeyPath:[bindingInformations valueForKey:NSObservedKeyPathKey]];
        if(items == nil) continue;
        // Get DataCell
        NSCell *columnDataCell = [column dataCell];
        NSMutableDictionary *att = [[NSMutableDictionary alloc] init];
        [att setValue:[columnDataCell font] forKey:NSFontAttributeName];
        CGFloat width = 5;
        // parse items
        for(NSString *v in items){
            CGFloat w = [[NSString stringWithFormat:@"%@", v] sizeWithAttributes:att].width;
            if(w>width) width = w;
        }
        // end
        width *= 1.1;
        width += [self intercellSpacing].width;
        // width += 1;
        // DCHLog(@"%@ width: %f", att, width);
        [att release];
        [column setWidth:width];
    }
}

@end