[Résolu] Une NSTableHeaderCell qui affiche un Popover

berfisberfis Membre
janvier 2017 modifié dans API AppKit #1

Bonjour,


 


Je cherche à  obtenir la fonctionnalité montrée dans l'image jointe.


 


En effet, les titres d'en-tête de colonnes peuvent être longs, alors que le contenu de la colonne peut se résumer à  un nombre, une lettre, ou une case à  cocher. Mon idée est donc d'afficher, un peu à  la manière d'un "tool tip", un popover, qui apparaà®trait lors du survol de l'en-tête, et qui permettrait également d'éditer le titre. Cela résoudrait à  la fois la lecture du titre complet et son édition (j'ai jeté un coup d'oeil aux différentes façons d'éditer un titre à  l'aide d'un double-clic, mais je ne suis pas convaincu par les solutions).


 


Je sous-classe donc NSTableHeaderCell, j'injecte cette sous-classe dans ma tableview, et tout se passe à  merveille... sauf que:


 


- Une cell n'est pas une view, elle n'a pas de "frame" ou de "bounds" pour positionner le popover.


- Pour savoir si la souris passe sur cette cell, pas moyen de définir un "tracking rect" pour la même raison.


- La méthode héritée de NSCell, startTrackingAt, qui est invoquée par trackMouse, n'est pas appelée.


 


Voici mes questions:


a. En admettant que cette manière soit la bonne, ai-je manqué une marche?


b. Faut-il que je m'y prenne autrement?


 


Merci d'avance !


Réponses

  • devulderdevulder Membre
    septembre 2016 modifié #2

    Bonjour,


     


    Tu peux mettre un tooltip standard dans ta column, exemple ici:


     


    http://macscripter.net/viewtopic.php?id=18993


     


    Vu sur Github, ce bout de code pour voir la position de la souris dans une NSCell


     


    https://gist.github.com/arufian/3616801


     


    Bon courage !

  • CéroceCéroce Membre, Modérateur


    Tu peux mettre un tooltip standard dans ta column, exemple ici:




    ça me semble aussi la solution la plus standard.


     


    Sinon, une solution simple ne serait-elle pas d'utiliser une NSTableView "view-based" plutôt que "cell-based" ?


     


    P.S.: NSPopover a vraiment été torché rapido; moi, ce qui me gène le plus, est qu'on ne peut pas en faire apparaitre depuis un NSToolbarItem. 

  • Bonjour,


     


    J'ai opté pour la solution suivante: je sous-classe NSTableHeaderView, de façon à  travailler sur une NSView et non une NSCell:



    - (void) awakeFromNib
    {
    NSTrackingArea* trackingArea = [[NSTrackingArea alloc]
    initWithRect:self.bounds
    options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways| NSTrackingMouseMoved
    owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
    self.headerRects = [NSMutableArray new];
    self.activeColumn = -1;
    }

    Plutot que de déterminer dans quelle Cell se trouve le curseur, je stocke leurs rectangles dans une array lors de l'entrée dans le Header et j'initialise la colonne courante à  -1 (aucune colonne)



    - (void)mouseEntered:(NSEvent *)theEvent
    {
    if (self.tableView.tableColumns.count ==0) return;
    [self.headerRects removeAllObjects];
    for (long i = 0; i<self.tableView.tableColumns.count;i++)
    [self.headerRects addObject:[NSValue valueWithRect:[self headerRectOfColumn:i]]];
    }

    Puis j'implémente mouseMoved, qui va être appelé à  chaque micro-déplacement du curseur. Pour filtrer les appels, je me base sur activeColumn:



    - (void) mouseMoved:(NSEvent *)theEvent
    {
    if (self.tableView.tableColumns.count ==0) return;
    NSPoint point = NSMakePoint(theEvent.locationInWindow.x-268, 10);
    long col = [self columnAtPoint:point];
    if (col !=-1 && col != self.activeColumn)
    {
    Column *column = self.tableView.tableColumns[col].headerCell.representedObject;
    float textWidth = [column.title sizeWithAttributes:nil].width;
    [self.textField setStringValue:column.title];
    [self.popover setContentSize:NSMakeSize(textWidth+12, 16)];
    [self.popover showRelativeToRect:[(NSValue*)self.headerRects[col] rectValue] ofView:self preferredEdge:NSMinYEdge];
    self.activeColumn = col;
    }
    }

    Il y a quelques détails d'implémentation que je vous passe: les outlets sur le popover et le text field qu'il contient; le fait que je stocke l'entité coredata Column dans le representedObject de la Cell; l'horrible NSPoint que j'ai simplifié de guerre lasse après m'être longuement battu avec convertPoint qui ne retournait pas les bonnes valeurs (NSTableView fonctionne avec une origine {top;left} (flipped) et non {bottom;left} comme le reste des vues...


     


    Reste la sortie du curseur:



    - (void)mouseExited:(NSEvent *)theEvent
    {
    [self.popover close];
    self.activeColumn = -1;
    }

    Ce qui nous donne, au final, l'aspect montré dans la capture d'écran jointe.


     


    Je reste ouvert aux remarques sur cette façon de faire " en fait un détail noyé dans le reste d'une application qui pour l'instant ne connaà®t pas encore le "undo/redo", c'est dire qu'il reste du travail...


     


    Merci pour l'idée du tool tip (la première qui m'est venue) mais on ne peut pas éditer un tool tip...


     


     


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