[Résolu]NSOutlineView cell based vs view based vs binding (couleur selon le niveau)

mybofymybofy Membre
mars 2014 modifié dans API AppKit #1

Objectif :


NSOutline à  une seule colonne, 3 niveaux de couleurs différentes, capture du clic de la souris.


 


1. Cell based par programme


Le code suivant marche : affichage en couleurs



//DataSource
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
if (item == nil) {
return [_dataSource count];
} else if ([item isKindOfClass:[NSDictionary class]]) {
return [[item objectForKey:@children] count];
} else return 0;
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
if (item == nil) { //item is nil when the outline view wants to inquire for root level items
return [_dataSource objectAtIndex:index];
} else if ([item isKindOfClass:[NSDictionary class]]) {
return [[item objectForKey:@children] objectAtIndex:index];
} else return nil;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
if ([item isKindOfClass:[NSDictionary class]] || [item isKindOfClass:[NSArray class]]) {
return YES;
} else {
return NO;
}
}

- (id)outlineView:(NSOutlineView *)outlineView :(NSTableColumn *)tableColumn byItem:(id)item
{
if ([item isKindOfClass:[NSDictionary class]]) {
NSLog(@[;item objectForKey:@'parent'] : %@", [item objectForKey:@parent]);
return [item objectForKey:@parent];
}
return item ;
}
//Delegate
- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
long level = [outlineView levelForItem:item];
[cell setTextColor:[NSColor colorWithRed:223./255. green:109./256. blue:20./255. alpha:1.0]];
if(level>0)
[cell setTextColor:[NSColor colorWithRed:30./255. green:127./256. blue:203./255. alpha:1.0]];
if(level>1)
[cell setTextColor:[NSColor colorWithRed:34./256. green:120./256. blue:15./256. alpha:1.0]];
}
- (NSString *)outlineView:(NSOutlineView *)outlineView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tc item:(id)item mouseLocation:(NSPoint)mouseLocation {
[self action:item];
return nil;
}


Problème :  méthode "toolTipForCell:(NSCell *)cell" OK. Mais il faut laisser le curseur de la souris plusieurs secondes pour que "action" soit appelée et affiche quelque chose, ce qui est trop long et peu naturel.


 


2. View based par programme


Avec le même code, c'est le titre de la NSTextFieldCell qui est affiché et pas en couleur.


C'est peut-être la méthode "objectValueForTableColumn" qui ne convient pas ?


J'ai essayé d'autres méthodes mais rien à  faire. Et je n'ai pas réussi à  adapter des bouts de code trouvés ici ou là .


L'intérêt est que le NSTextField peut être sous-classé et permettre ainsi la gestion instantanée des clics de la souris. Mais si l'affichage n'est pas le bon...


 


3. View based par binding dans le XIB


C'est assez facile dans le XIB et avec un NSTree, en mode view based


Je récupère les clics de la souris comme je veux.


Problème : il semble que le Delegate soit inopérant, donc pas de couleurs.


Le DataSource aussi d'ailleurs, semble-t-il ?


 


 


Réponses

  • CéroceCéroce Membre, Modérateur

    3. View based par binding dans le XIB
    Problème : il semble que le Delegate soit inopérant, donc pas de couleurs.
    Le DataSource aussi d'ailleurs, semble-t-il ?

    C'est normal que la datasource soit inopérante, puisqu'elle est remplacée par le binding.
    Par contre, le delegate doit fonctionner.
  • OK pour le DataSource.


     


    Le Delegate ne répond pas et je n'ai pas vu d'autre méthode qui semble adaptée.



    _outlineViewCtrl = [[OutlineViewCtrl alloc] initWithNibName:@OutlineViewCtrl bundle:nil];
    _listeDelegate = [ListeDelegate new];
    [[_outlineViewCtrl outlineView] setDelegate:(id<NSOutlineViewDelegate>)_listeDelegate];

    //Delegate
    - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item {
    NSLog(@willDisplayCell);
    long level = [outlineView levelForItem:item];
    [cell setTextColor:[NSColor colorWithRed:223./255. green:109./256. blue:20./255. alpha:1.0]];
    if(level>0)
    [cell setTextColor:[NSColor colorWithRed:30./255. green:127./256. blue:203./255. alpha:1.0]];
    }


    La méthode n'est jamais appelée, alors que c'est la même que dans le 1.


    Faut-il faire un binding sur le Delegate ? Si oui, je n'ai pas vu comment.

  • samirsamir Membre

    Bonsoir,    _listeDelegate = [ListeDelegate new];



    [[_outlineViewCtrl outlineView] setDelegate:(id<NSOutlineViewDelegate>)_listeDelegate];

    Je trouve ce code un peux bizarre, c'est quoi ListeDelegate ? ce n'est pas plutot OutlineViewCtrl le delegate de ta vue outlineView ?


    Donc un truc du genre :



    [_outlineViewCtrl.outlineView setDelegate:(id<NSOutlineViewDelegate>)self];
  • ListeDelegate est une sous classe de NSObject avec <NSOutlineViewDelegate> qui isole le delegate plutôt que de le fourrer dans OutlineViewCtrl.


    Il y a           


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



    qui répond.

    Mais il faut que j'arrive à  m'en servir, cf. exemple Apple SidebarDemo.

  • CéroceCéroce Membre, Modérateur
    mars 2014 modifié #6

    [[_outlineViewCtrl outlineView] setDelegate:(id<NSOutlineViewDelegate>)_listeDelegate];

    Pourquoi transtyper _listDelegate ? Il se conforme au protocole NSOutlineViewDelegate, oui ou non ?
  • Ci-attaché, une application minimale view based + binding.


  • Bon, puisque je n'arrive pas à  avoir fromage (clic de la souris) et dessert (couleur selon) le niveau, je choisis le fromage.


    C'est à  dire NSOutlineView  view based  avec binding. 


     


    Merci à  tous.


  • colas_colas_ Membre
    mars 2014 modifié #9

    Salut, 


     


    je pense avoir réussi à  faire ce que tu veux.


     


    En fait, dans un view-based outlineView, il n'y a pas de cell. Donc, les méthodes delegate ne sont pas appelées.


    Tu peux t'en sortir avec d'autres méthodes déléguées.



    - (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
    {
    NSInteger row = [self.outlineView rowForItem:item] ;


    NSTableCellView * cell = [self.outlineView viewAtColumn:0 row:row makeIfNecessary:NO];


    long level = [self.outlineView levelForItem:item];
    [cell.textField setTextColor:[NSColor redColor]];
    if(level>0)
    [cell.textField setTextColor:[NSColor blueColor]];
    if(level>1)
    [cell.textField setTextColor:[NSColor greenColor]];

    return YES ;
    }

    ci-joint un toy project qui marche.


     


     


    PS : tu aurais pu aussi t'en sortir en gérant à  la main le datasource


  • mybofymybofy Membre
    mars 2014 modifié #10

    Cola


     


    J'ai aussitôt essayé ta modification.


    Elle ne marche pas chez moi (Mavericks) : message


    .../MainMenu.xib: Outlet 'delegate' of 'Text Field - Table View Cell' is connected to 'File's Owner,' an invalid destination (Objects inside view based table views may only be connected to the table view's delegate.)


    Normal, car en mode binding, le NSOutlineViewDataSource est inopérant (remplacé par le binding, cf. Céroce), seul le NSOutlineViewDelegate est opérant.


     


    Cela fait plusieurs jours que je tourne autour de la méthode :


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


    Je n'arrivais pas à  trouver le "level".


     


    Miracle ! tu m'as fourni la solution : 


     long level = [self.outlineView levelForItem:item];


    Le reste est sans problème.


     


    Grâce à  toi j'ai fromage ET dessert :


  • colas_colas_ Membre
    mars 2014 modifié #11

    Content de t'avoir aidé 


     


    Essaye si tu veux cette nouvelle version. Elle ne devrait pas buguer.


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