6
votes

Affichage de l'indice de ligne dans une nstableview liée à NsarrayController

J'ai une vision nstable qui est liée à un NsarrayController. J'aimerais avoir l'une des colonnes de table montrant l'index de la ligne de table. Ceci est suffisamment facile à faire lorsque vous implémentez NSTABLATAsource vous-même, mais je ne peux pas le comprendre avec une vue de table liée. Je suppose que je cherche ici quelque chose comme le chemin de la clé @Count qui me donne le nombre d'arrangementsObjects (c'est @index) mais cela manque évidemment.

Deux clarifications:

  1. L'index indiqué dans chaque ligne est l'index de cette ligne et non liée à la manière dont les données sont en réalité disposées dans le contrôleur de modèle ou de tableau. Par exemple, si l'ensemble des données est de 10000 éléments, les index doivent passer de 1 à 10000, si l'utilisateur entre dans un terme de recherche et que le tableau indique seulement 4 des éléments, les chiffres doivent alors passer de 1 à 4, même si le Les éléments affichés sont réellement de partout dans le tableau d'origine.
  2. J'en ai besoin parce que j'ai été invité à le faire par le client :-). Le client a besoin d'un moyen de pouvoir estimer le nombre de lignes avant ou après une certaine rangée. Salut pourrait, par exemple, je veux savoir combien de lignes ont été ajoutées.

1 commentaires

N'importe quelle raison? La seule application à laquelle je peux penser que cela est aujourd'hui iTunes et je n'ai jamais trouvé de but pour cette fonctionnalité.


3 Réponses :


1
votes

En supposant que vous visez à reproduire le comportement d'iTunes, votre colonne doit seulement afficher 1 à (nombre de lignes visibles). Il n'a pas réellement besoin de se rapporter à votre modèle du tout.

Donc, donnez à votre contrôleur une propriété généralisée générée dynamiquement et faites-la dépend sur le tableau des objets de modèle réels.

Pour cette propriété, implémentez le Méthodes d'accesseur de tableau , avec le getter indexé simplement informatique IDX + 1 , BOÎTE INGER IT UP et retourner cet objet. Vous devrez peut-être également mettre en œuvre l'ensemble de la getter totale pour satisfaire KVC.

Assurez-vous que la colonne est définie comme non modifiable et que le jeu de liaison n'est pas défini sous condition activé . Sinon, vous obtiendrez une exception (pour ne pas avoir de setters pour cette propriété) lorsque l'utilisateur tente d'entrer un nouvel index pour une ligne.

Une note de prudence: cela peut entraîner des problèmes, car NSTableView ne s'attend pas à ce que ses colonnes soient liées à des tableaux discrets; Il s'attend à ce que toutes ses colonnes soient liées à différentes propriétés des objets de modèle dans un seul tableau. Vous devrez peut-être lier le contenu de la vue de tableau elle-même sur votre matrice d'objets de modèle, en plus de la liaison des liaisons de contenu des colonnes et J'ai eu des problèmes avec cela avant .


2 commentaires

J'essaie de mettre en œuvre cela, mais le lien se brise maintenant et la recherche Apple sur "Model Objects" n'apparose rien qui semblent utile.


@boyfarrell: Merci pour la tête. La recherche que j'ai utilisée pour trouver le nouveau lien était "Modèles d'objet Accessor Méthodes". J'ai mis à jour les liens de documentation de mes réponses.



4
votes

Si je comprends bien, vous pouvez choisir de ne pas lier cette colonne de table et utiliser une source de données à la place. Je me souviens que NSTableView prend en charge ce type de "mode double", mais je ne trouve aucun doctorat pour le confirmer.


3 commentaires

Merci! La solution était assez simple. J'ai ajouté une colonne qui n'était pas liée à quoi que ce soit, puis j'ai défini la prise de données de la vue de la table entière sur le propriétaire du fichier, puis implémentée NSTAbAtaSource renvoyant l'index de la colonne lorsqu'il est demandé au contenu de la colonne.


Je dois faire cela, mais ma méthode de DataSource solitaire mise en œuvre est en train d'être appelée à d'autres visuelles et colonnes. Mon délégué / DataSource a été marqué à l'origine pour les tableaux prenant en charge Drag-N-Drop. Ne devrais-je pas obtenir un seul rappel pour cette colonne dans une seule tableView? Tous les autres cols sur d'autres tablevies ont des liaisons!


BTW, le comportement diffère grandement si la vision de la table est une cellule (historique) ou une vue (nouveau à partir de 10,6?) Basé. Il n'est apparemment pas faisable du tout avec ce dernier, mais le comportement des cellules à glisser-n-goutte (besoin de réarrangement de l'utilisateur) diffère. Oui comme iTunes, c'est une sorte de liste de playlist Besoin d'où la commande est la clé.



2
votes

J'ai récemment mis en œuvre ceci à l'aide d'une sous-classe Nsruler qui dessine les numéros de ligne à côté de chaque ligne de la vue. J'ai basé le code sur quelque chose de similaire que j'ai trouvé ici .

Vous pouvez ajouter ceci à votre tableView en utilisant: p> xxx pré>

voici le fichier d'interface: p> xxx pré>

Voici la mise en œuvre: p>

//
//  TableLineNumberRulerView.m
//  Line View Test
//
//  Created by Ben Golding, Object Craft Pty Ltd on 7 May 2014.
//  Based on code by Paul Kim on 9/28/08.

#import "TableLineNumberRulerView.h"

#define DEFAULT_THICKNESS   22.0
#define RULER_MARGIN        5.0

@implementation TableLineNumberRulerView

@synthesize font;
@synthesize textColor;
@synthesize alternateTextColor;
@synthesize backgroundColor;
@synthesize textAttributes;
@synthesize rowCount;


- (id)initWithTableView:(NSTableView *)tableView usingArrayController:(NSArrayController *)arrayController
{
    NSScrollView *scrollView = [tableView enclosingScrollView];

    if ((self = [super initWithScrollView:scrollView orientation:NSVerticalRuler]) == nil)
        return nil;

    [self setClientView:tableView];

    self.arrayController = arrayController;
    [arrayController addObserver:self forKeyPath:@"arrangedObjects" options:NSKeyValueObservingOptionNew context:nil];

    self.font = [NSFont labelFontOfSize:[NSFont systemFontSizeForControlSize:NSMiniControlSize]];
    self.textColor = [NSColor colorWithCalibratedWhite:0.42 alpha:1.0];
    self.alternateTextColor = [NSColor whiteColor];
    self.textAttributes = @{
        NSFontAttributeName: [self font],
        NSForegroundColorAttributeName: [self textColor]
    };

    self.rowCount = [[arrayController arrangedObjects] count];

    return self;
}

- (void)awakeFromNib
{
    [self setClientView:[[self scrollView] documentView]];      // this will be an NSTableView instance
}

- (void)finalize
{
    [self.arrayController removeObserver:self forKeyPath:@"arrangedObjects"];
}

#pragma mark -
#pragma mark Key-Value observing of changes to array controller

/*
 * This picks up changes to the arrayController's arrangedObjects using KVO.
 * We check the size of the old and new rowCounts and compare them to see if the number
 * digits has changed, and if so, we adjust the ruler width.
 */

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"arrangedObjects"]) {
        NSUInteger newRowCount = [[self.arrayController arrangedObjects] count];

        if ((int)log10(self.rowCount) != (int)log10(newRowCount))
            [self setRuleThickness:[self requiredThickness]];
        self.rowCount = newRowCount;
        // we need to redisplay because line numbers may change or disappear in view
        [self setNeedsDisplay:YES];
    }
}


- (CGFloat)requiredThickness
{
    NSUInteger      lineCount = [[self.arrayController arrangedObjects] count],
                    digits = (unsigned)log10((lineCount < 1) ? 1: lineCount) + 1;
    NSMutableString *sampleString = [NSMutableString string];
    NSSize          stringSize;

    for (NSUInteger i = 0; i < digits; i++) {
        // Use "8" since it is one of the fatter numbers. Anything but "1"
        // will probably be ok here. I could be pedantic and actually find the fattest
        // number for the current font but nah.
        [sampleString appendString:@"8"];
    }

    stringSize = [sampleString sizeWithAttributes:[self textAttributes]];

    // Round up the value. There is a bug on 10.4 where the display gets all wonky when scrolling if you don't
    // return an integral value here.
    return ceil(MAX(DEFAULT_THICKNESS, stringSize.width + RULER_MARGIN * 2));
}

- (void)drawHashMarksAndLabelsInRect:(NSRect)aRect
{
    NSTableView *tableView = (NSTableView *)[self clientView];
    NSRect bounds = [self bounds];
    NSRect visibleRect = [[tableView enclosingScrollView] documentVisibleRect];
    NSRange visibleRowRange = [tableView rowsInRect:visibleRect];
    CGFloat yinset = NSHeight([[tableView headerView] bounds]);

    if (backgroundColor != nil) {
        [backgroundColor set];
        NSRectFill(bounds);

        [[NSColor colorWithCalibratedWhite:0.58 alpha:1.0] set];
        [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(bounds) - 0/5, NSMinY(bounds))
                                  toPoint:NSMakePoint(NSMaxX(bounds) - 0.5, NSMaxY(bounds))];
    }

//    NSLog(@"drawHashMarksAndLabelsInRect: bounds %@, ruleThickness %lf", NSStringFromRect(bounds), [self ruleThickness]);

    for (NSUInteger row = visibleRowRange.location; NSLocationInRange(row, visibleRowRange); row++) {
        // Line numbers are internally stored starting at 0
        NSString *labelText = [NSString stringWithFormat:@"%lu", row + 1];
        NSSize stringSize = [labelText sizeWithAttributes:self.textAttributes];
        NSRect rowRect = [tableView rectOfRow:row];
        CGFloat ypos = yinset + NSMinY(rowRect) - NSMinY(visibleRect);

        [labelText drawInRect:NSMakeRect(NSWidth(bounds) - stringSize.width - RULER_MARGIN,
                                         ypos + (NSHeight(rowRect) - stringSize.height) / 2.0,
                                         NSWidth(bounds) - RULER_MARGIN * 2.0, NSHeight(rowRect))
               withAttributes:self.textAttributes];
    }
}

#pragma mark -
#pragma mark NSCoding methods

#define FONT_CODING_KEY         @"font"
#define TEXT_COLOR_CODING_KEY       @"textColor"
#define ALT_TEXT_COLOR_CODING_KEY   @"alternateTextColor"
#define BACKGROUND_COLOR_CODING_KEY @"backgroundColor"

- (id)initWithCoder:(NSCoder *)decoder
{
    if ((self = [super initWithCoder:decoder]) != nil) {
        if ([decoder allowsKeyedCoding]) {
            font = [decoder decodeObjectForKey:FONT_CODING_KEY];
            textColor = [decoder decodeObjectForKey:TEXT_COLOR_CODING_KEY];
            alternateTextColor = [decoder decodeObjectForKey:ALT_TEXT_COLOR_CODING_KEY];
            backgroundColor = [decoder decodeObjectForKey:BACKGROUND_COLOR_CODING_KEY];
        } else {
            font = [decoder decodeObject];
            textColor = [decoder decodeObject];
            alternateTextColor = [decoder decodeObject];
            backgroundColor = [decoder decodeObject];
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [super encodeWithCoder:encoder];

    if ([encoder allowsKeyedCoding]) {
        [encoder encodeObject:font forKey:FONT_CODING_KEY];
        [encoder encodeObject:textColor forKey:TEXT_COLOR_CODING_KEY];
        [encoder encodeObject:alternateTextColor forKey:ALT_TEXT_COLOR_CODING_KEY];
        [encoder encodeObject:backgroundColor forKey:BACKGROUND_COLOR_CODING_KEY];
    } else {
        [encoder encodeObject:font];
        [encoder encodeObject:textColor];
        [encoder encodeObject:alternateTextColor];
        [encoder encodeObject:backgroundColor];
    }
}

@end


0 commentaires