Implémenter une OutlineView correctement...

CirdoCirdo Membre
avril 2015 modifié dans API AppKit #1

Salut à  tous,

 

J'aimerais implémentée une OutlineView correctement.

 

J'ai une classe qui me sert d'item qui s'appelle cours qui pointe sur l'object ZCours. Elle contient un titre (title) et des enfants (chapitre). L'enfant à  aussi des enfants (sousChapitre).

 

 

Voici mon code qui de mon controller qui gère pour l'instant il est très basique.



#import "ZReadController.h"
#import "ZCours.h"
#import "ZCoursCreate.h"
@interface ZReadController ()
@property ZCours *cours;
@end

@implementation ZReadController

- (void)viewDidLoad {
[super viewDidLoad];
// Do view setup here.
_cours = [[[ZCoursCreate alloc] init] createCoursWithPath:[NSURL URLWithString:@/Users/Odric/Downloads/developpez-votre-site-web-avec-le-framework-django]]; //C'est un test à  la va vite. Donc c'est de mon plein grès si c'est comme ça :)
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{
return [[[_cours chapitre] objectAtIndex:index] title];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item{
return YES;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item{

return [[_cours chapitre] count];
}

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item{

NSLog(@%@", [item description]);
NSTableCellView *result = [outlineView makeViewWithIdentifier:@DataCell owner:self];


[[result textField] setStringValue:item];
return result;

}

- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item{
NSInteger row = [outlineView rowForItem:item];
return [tableColumn dataCellForRow:row];
}


@end


Est-ce plus correcte que la variable 'item' du delegate et de la source soit un pointeur sur l'object _cours ? Ou de faire comme le code en haut, c'est à  dire que la variable item soit une NSString ?


 


Quel est selon vous la meilleure solution ? (C'est possible que je sois à  coté de la plaque pour les solutions que j'ai proposé :) )


Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur
    Je crois comprendre la question. Les deux approches sont valables.

    Historiquement, on disait "l'objet associé à  telle cellule est celui-ci". C'était assez nécessaire parce qu'on travaillait avec des NSCells.

    En travaillant avec des NSTableCellViews, on a d'avantage de liberté, et il me semble souvent plus simple de la configurer directement, en accédant à  son textField et son imageView.
  • En gros ça revient aux même si je fait :



    - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{
    return [[[_cours chapitre] objectAtIndex:index] title];
    }

    Ou :



    - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{
    return [[_cours chapitre] objectAtIndex:index];
    }

    Sauf que la deuxième méthode il faudra implémenter une méthode copyWithZone: Et ré-écrire la méthode description. Mais elle est très facile à  implementer.


     


    Par contre l'autre (la première) est plus difficile car il faudra faire du parcours dans les sous-chapitre si l'utilisateurs choisit un sous-chapitre dans outlineview. (Je sais pas si tu me suis ? )


     


    Merci pour ta réponse :)


  • CéroceCéroce Membre, Modérateur
    avril 2015 modifié #4

    Sauf que la deuxième méthode il faudra implémenter une méthode copyWithZone: Et ré-écrire la méthode description.

    Non. Une NSTableViewCell ne sait pas spontanément comment afficher un 'chapitre'. Elle se rabat donc sur sa méthode -description.
    Il faut créer une sous-classe de NSTableViewCell.

    Mais aujourd'hui, utiliser des tables "cell-based" est dépassé; préfère des table "view-based", qui se reposent sur des NSTableCellViews, c'est plus simple.
  • CirdoCirdo Membre
    avril 2015 modifié #5

    Je vais peut être posé une question bête mais le code qui j'ai écrit est pour une table "cell-based" ? 


  • CéroceCéroce Membre, Modérateur

    Non, elle est bien "view-based", puisque tu as implémenté la méthode:



    - (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item

    Il y a peu de raisons d'employer une table "cell-based" à  moins de vouloir binder vite-fait ou d'assurer la compatibilité avec une version antérieure à  10.7.


  • Je vais implémenter une table "view-based". Et créé une sous-class de NSTableViewCells pour afficher les bonnes informations.


  • Je vais encore posée une question bête. Pourquoi faire sous-class de NSTableViewCell ? Car je comprends pas bien  ???

  • CéroceCéroce Membre, Modérateur

    Cell-based: NSTableViewCell


    View-based: NSTableCellView. Pas forcément nécessaire de sous-classer, elle comprend un textField et une imageView.


  • Pour l'instant j'ai fait ça :



    - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{
    if (!item){
    return [[_cours chapitre] objectAtIndex:index];

    }else if ([item isKindOfClass:[ZChapitre class]]){
    return [[item sousChapitre] objectAtIndex:index];

    }else if ([item isKindOfClass:[ZSousChapitre class]]){
    return [[item partie] objectAtIndex:index];
    }

    return nil;
    }
    - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item{
    return ([item isKindOfClass:[ZSousChapiterPartie class]] || [item isKindOfClass:[ZIntroduction class]]) ? NO : YES;
    }
    - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item{
    if (!item){
    return [[_cours chapitre] count];

    }else if ([item isKindOfClass:[ZChapitre class]]){
    return [[item sousChapitre] count];

    }else if ([item isKindOfClass:[ZSousChapitre class]]){
    return [[item partie] count];
    }

    return 0;


    }
    - (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item{
    NSTableCellView *result = [outlineView makeViewWithIdentifier:@DataCell owner:self];
    if ([item isKindOfClass:[ZIntroduction class]]){
    [[result textField] setStringValue:@Introduction];
    }else{
    [[result textField] setStringValue:[item title]];
    }
    return result;

    }

    - (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item{
    NSInteger row = [outlineView rowForItem:item];
    return [tableColumn dataCellForRow:row];
    }
    - (void)outlineViewSelectionDidChange:(NSNotification *)notification{
    if ([self.outlineView selectedRow] != -1){
    id item = [self.outlineView itemAtRow:[self.outlineView selectedRow]];

    if ([item isKindOfClass:[ZChapitre class]]){
    ZChapitre *coursItem = item;
    if (!coursItem.introduction.textMarkdown){
    return;
    }
    if (!coursItem.introduction.textHTML){
    [coursItem.introduction transform];
    }

    [[self.webView mainFrame] loadHTMLString:coursItem.introduction.textHTML baseURL:nil];

    }else if ([item isKindOfClass:[ZSousChapitre class]]){

    ZSousChapitre *chapitreItem = item;
    if (!chapitreItem.introduction.textHTML){
    [chapitreItem.introduction transform];
    }

    [[self.webView mainFrame] loadHTMLString:chapitreItem.introduction.textHTML baseURL:nil];

    }else if ([item isKindOfClass:[ZSousChapiterPartie class]]){
    ZSousChapiterPartie *chapitreItem = item;
    if (!chapitreItem.textHTML){
    [chapitreItem transform];
    }

    [[self.webView mainFrame] loadHTMLString:chapitreItem.textHTML baseURL:nil];
    }else if ([item isKindOfClass:[ZIntroduction class]]){
    ZIntroduction *i = item;
    if (!i.textHTML){
    [i transform];
    }
    [[self.webView mainFrame] loadHTMLString:i.textHTML baseURL:nil];
    }



    }
    }


    Est-ce correcte ? 


  • CéroceCéroce Membre, Modérateur

    J'ai pas regardé tous les détails, mais il me semble que oui.


Connectez-vous ou Inscrivez-vous pour répondre.