custom NSTableView (modification apparence)

wiskywisky Membre
01:47 modifié dans API AppKit #1
Bonjour à  tous,

Pour ceux que cela peut intéresser j'ai trouver une page très intéressante sur la modification de l'apparence d'une NSTableView. C'est par là  :
http://www.cocoadev.com/index.pl?NSTableViewInFinderWindows

Je tente de reproduite l'application qu'ils ont fait. Dès que je maitrise le tout je ferai un petit doc en français pour réaliser les modifications plus facilement. :adios!:

Je suis intéresser par la modification d'un NSOutlineView pour ajouter avant le nom une image et une case à  cocher. ::)

Réponses

  • wiskywisky Membre
    01:47 modifié #2
    Je vous livre le projet xcode tel que j'ai réussi à  le reconstituer. Il ne fonctionne pas et je n'arrive pas à  savoir pourquoi. Mon anglais est tellement pitoyable que j'ai pas du comprendre un partie :'(

    Si quelqu'un arrive à  comprendre mon problème ça serais super sympa.
    Je vous donne les sources qui m'ont servi:
    http://homepage.mac.com/tylers/Development/index.html
    http://www.cocoadev.com/index.pl?NSTableViewInFinderWindows

    Un grand merci d'avance  o:)

    [Fichier joint supprimé par l'administrateur]
  • wiskywisky Membre
    01:47 modifié #3
    Je me répond ;)

    Il y a une façon plus simple d'arrivé au même résultat : http://www.stepwise.com/Articles/Technical/2003-12-20.01.html

    ça peut intéresser quelqu'un ! :P
  • LeChatNoirLeChatNoir Membre, Modérateur
    01:47 modifié #4
    Salut,
    J'ai voulu essayer mais il me gueule dessus car les 3 images sont absentes de ton zip...
    Si tu veux que je regarde quand meme, tu peux reposter ?
  • wiskywisky Membre
    01:47 modifié #5
    En effet elle était dans un autre dossier. Je les aient ajouté.
    Si tu arrive à  le faire fonctionner ce serai super car j'en aurai besoin bientôt. Pour le moment j'utilise une solution plus simple.  :)

    [Fichier joint supprimé par l'administrateur]
  • BruBru Membre
    01:47 modifié #6
    J'ai regardé le code...
    Je le trouve ni clair, ni propre.

    De plus, il s'agit apparemment de recréer la liste telle que celle des comptes utilisateurs, ou celle dans la barre latérale des fenêtres Finder...
    Mais dans ce cas, il y a une contradiction dans le code, puisque lors du défilement de la liste, il y a aussi risque de faire défiler le "bouton" situé en bas (la "maison" dans les comptes utilisateurs).

    Je ne sais pas ce que tu veux vraiment obtenir, mais une liste comme celles des comptes utilisateurs est assez facile à  obtenir...

    .
  • wiskywisky Membre
    01:47 modifié #7
    Ce que je cherche c'est créer une liste comme les comptes utilisateurs car pour l'autre j'ai réussi sauf le séparateur ;)
  • cargocargo Membre
    01:47 modifié #8
    bonjour à  tous
    back in the business....
    dur de s'y recoller après environ 6 mois d'interruption...
    ce qui m'intéresse ici c'est le fait de mettre deux valeurs l'une en dessous de l'autre dans une "case" d'un tableau (Untel Admin pour reprendre l'exemple).
    je pige pas vraiment le principe de base au vu des codes sources.
    qu'est ce que l'on doit sous-classer ? NSCell, NSTableColumn ? et que lui demande -t-on à  cette NSCell ?
    si quelqu'un peut me mettre sur la piste...
  • wiskywisky Membre
    01:47 modifié #9
    Ce que j'ai reproduit dans mon projet est plus simple que ce que j'ai essayez de faire avec le code que j'ai mis plus haut.
    Comme expliqué ici : http://www.stepwise.com/Articles/Technical/2003-12-20.01.html
    Tu créer un contrôler et une surcharge de NSCell. Lors du chargement de la NIB tu affecte à  la colonne la surcharge de NSCell comme type de donnée. Cette dernière prend en charge la réception d'une vue comme donnée et se charge de l'affichage. C'est une façon simple d'arrivé au même résultat.
    La surcharge de NSTableView n'est là  que pour changé l'apparence de la sélection ou du fond de cellule. Si tu m'a compris, bravo!! Mais le mieux est d'aller voir le lien et regarder comment tout s'imbrique. Pour ma part, j'ai compris comme ça. Mais j'ai pas encore compris comment fonctionne le code que j'ai mis plus haut! :adios!: :adios!:
  • BruBru Membre
    février 2007 modifié #10
    dans 1170616005:

    ce qui m'intéresse ici c'est le fait de mettre deux valeurs l'une en dessous de l'autre dans une "case" d'un tableau (Untel Admin pour reprendre l'exemple).
    je pige pas vraiment le principe de base au vu des codes sources.
    qu'est ce que l'on doit sous-classer ? NSCell, NSTableColumn ? et que lui demande -t-on à  cette NSCell ?
    si quelqu'un peut me mettre sur la piste...


    dans 1170618637:

    Tu créer un contrôler et une surcharge de NSCell. Lors du chargement de la NIB tu affecte à  la colonne la surcharge de NSCell comme type de donnée. Cette dernière prend en charge la réception d'une vue comme donnée et se charge de l'affichage. C'est une façon simple d'arrivé au même résultat.


    Pour un simple cell sur 2 lignes (les 2 valeurs l'une en dessous de l'autre), pas besoin de sub-classer quoi que ce soit.

    Il suffit de renvoyer un attributedString à  la place d'un string...
    Un attributedString permet de contenir des sauts de lignes, et permet de fixer des attributs à  l'intérieur de la ligne.

    L'exemple qui suit renvoie un attributedString sur 2 lignes, la première en gras et grand caractère, la seconde en plus petit :
    <br />- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex<br />{<br />   NSData *d;<br />   NSAttributedString *as;<br /><br />   d=[@&quot;&lt;html&gt;&lt;bold&gt;&lt;font size=+2&gt;ligne 1&lt;/font&gt;&lt;/bold&gt;&lt;br&gt;&lt;font size=-1&gt;ligne 2&lt;/font&gt;&lt;/html&gt;&quot; dataUsingEncoding:NSASCIIStringEncoding];<br />   as=[[[NSAttributedString alloc] initWithHTML:d documentAttributes:nil] autorelease];<br /><br />   return as;<br />}<br />
    

    Ici, l'attributedString est construit à  partir d'un texte en html, mais ce n'est pas le seule méthode pour en fabriquer...

    .
  • cargocargo Membre
    01:47 modifié #11
    Merci Bru, bon, j'essaye de formuler ce que j'ai compris :
    - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
    

    Ca c'est un protocole NSTableDataSource, on est au niveau de la vue, de l'affichage des données, on touche uniquement à  l'interface.
    Dans mon appli CoreData document-based, rien à  modifier au niveau des entités et de leurs attributs (modèle), rien à  modifier au niveau de mon NSArrayController crée dans IB (contrôleur) et bindé à  ma tableView (vue).
    Je travaille donc sur la vue :
    - Je crée des IB outlets pour la tableView et la tableColumn.
    - Je déclare et j'implémente cette fonction dans monDocument (contrôleur de mon appli).
    - A chaque refresh de la table cette fonction sera appelée automatiquement. Ca ça me paraà®t bizarre étant donné que je ne sous-classe rien, pourquoi c'est ma fonction qui sera appelée et pas celle "par défaut" du protocole du framework. Parce que j'ai crée des outlets ? (faut que je revois mes bases moi...)
    - Pour ce qui est de rowIndex, si je souhaite que toutes les cellules de ma colonne soient systématiquement affichées sur 2 lignes, je crée une boucle du type for (i=0, i++, etc).
    - Mes valeurs étant bien sûr dynamiques, le "ligne 1  ligne 2" de l'exemple sera remplacé par un valueForKey (key coding). Je ne suis pas sûr là ...en fait on ne peut pas utiliser le keycoding au milieu d'un string html, si ?
    Je me demande si il ne faut pas plutôt que je "convertisse" mes NSManagedObject (Coredata) en NSData (c'est possible à  faire) et que j'utilise :
    initWithData:myData options:nil documentAttributes:nil error:nil
    


    J'ai bon ?

  • cargocargo Membre
    01:47 modifié #12
    Bon j'ai fait une appli test, je ne pige rien.
    Comment intégrer cette fonction dans mon appli ? Je ne vois pas...
  • BruBru Membre
    01:47 modifié #13
    Je me trompe, mais... Tu n'utilises que les bindings pour tes table ?

    Si oui, alors tu es passé à  côté de plein de choses...
    Notamment comment un tableView fonctionne fondamentalement.

    Si je trouve un 'tit moment, je te ferais un projet test qui explique ça.

    .
  • cargocargo Membre
    février 2007 modifié #14
    Autant pour moi, avec Coredata je pense qu'il faut passer par une derived value comme expliqué dans l'exemple "Document-based application" (on y montre comment concaténer First Name Last Name)

    Pour répondre à  Bru, je crois avoir compris que sans les bindings et coredata, on "remplit" une tableView avec des NSArray etc (j'ai lu entre autres l'exemple "carnet d'adresse" sur project omega qui explique bien ça).
    Pour le projet exemple que tu proposes c'est sûr que ça peut être utile à  tous les débutants !
  • BruBru Membre
    01:47 modifié #15
    dans 1171120688:

    Si je trouve un 'tit moment, je te ferais un projet test qui explique ça.


    .

    [Fichier joint supprimé par l'administrateur]
  • skimpyskimpy Membre
    01:47 modifié #16
    Bonjour,

    Ce sujet de personnalisation des TableView m'intéresse car je pense que j'en aurai besoin dans quelques temps. J'ai vu qu'il existait certains sites qui traitaient de ce sujet mais j'aimerais vraiment avec votre aide essayer de comprendre le mécanisme :

    -  Imaginons que nous ayons une TableView composée de 2 colonnes :
      - la 1ère colonne contient un numéro (un id)
      - la 2ème colonne contient du texte avec tout à  droite une image

    Est-ce que mon raisonnement suivant est bon ?

    1. Sous-classer NSCell et surcharger la méthode drawWithFrame:inView:
    2. Dans cette méthode, récupérer la largeur et la hauteur de la cellule (avec un cellFrame.size.width et .height)
    3. Calculer l'emplacement x et y du texte ainsi que de l'image
    4. Insérer le texte en utilisant la méthode drawAtPoint:
    5. Insérer l'image en utilisant la méthode compositeToPoint:operation:
    6. Dans le contrôleur de l'application, définir par un setDataCell le type de la colonne n°2 (à  savoir la classe que l'on vient de créer)
    7. Dans la méthode data source tableView:objectValueForTableColumn:row:, implémenter le code en fonction de l'identifiant de la colonne

    Est-ce que ceci n'est pas trop simpliste et y'a-t'il des notions à  connaà®tre absolument ?

    Merci.
  • cargocargo Membre
    01:47 modifié #17
    Merci Bru, c'est plus clair pour moi maintenant.
    C'est vrai que quand on fait tout "à  la main" on a plus de contrôle sur le code, et c'est plus concret, on voit bien ce qu'on fait. Effectivement je passe à  côté de quelque chose....le fameux "glue code"...
    Pour mon appli, je vais voir si je peux obtenir le même résultat avec les derived value dans Coredata et je post une solution ici si je m'en sors.
  • cargocargo Membre
    01:47 modifié #18
    C'est bon, ça gaze...Il faut passer par une derived value.
    Ci-dessous le code de mon appli test avec une entité "Employee" et 3 attributs : 2 attributs strings ("name", "age") et un attribut transient "full" qui résulte de la concaténation des deux autres.
    Le résultat est une case de tableView où "name" et "age" sont sur 2 lignes, la première ligne est en police système gras et la deuxième en police système normale.
    Bru merci, ta petite fonction C qui va bien m'a été très utile pour me rendre compte qu'il fallait que je passe par un NSMutableAttributedString pour pouvoir concaténer.

    N.B: Peut-être quelques releases à  ajouter au code mais le principe est là . Au niveau MVC, peut-être que ce n'est pas ce qu'il y a de mieux, étant donné que je met en forme du texte dans un fichier du type maClasse(monEntité).m

    <br />@implementation Employee <br /><br />+ (void)initialize {<br />&nbsp; &nbsp; if (self == [Employee class])<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSArray *keys = [NSArray arrayWithObjects:<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @&quot;name&quot;, @&quot;age&quot;, nil];<br />&nbsp; &nbsp; &nbsp; &nbsp; [self setKeys:keys<br />triggerChangeNotificationsForDependentKey:@&quot;full&quot;];<br />&nbsp; &nbsp; }<br />}<br /><br />- (NSMutableAttributedString*) full<br />{<br /><br />NSString *string1= [NSString stringWithFormat:@&quot;%@&quot;, [self valueForKey:@&quot;name&quot;]];<br />NSFont *font1 = [NSFont boldSystemFontOfSize:[NSFont systemFontSize]];<br />NSDictionary *dict1 = [NSDictionary dictionaryWithObject:font1 forKey:NSFontAttributeName];<br />NSMutableAttributedString *line1 = [[NSMutableAttributedString alloc] initWithString:string1 attributes:dict1];<br /><br />NSMutableAttributedString *line2 = [[NSMutableAttributedString alloc] initWithString:@&quot;&#092;n&quot;];<br /><br />NSString *string3= [NSString stringWithFormat:@&quot;%@&quot;, [self valueForKey:@&quot;age&quot;]];<br />NSFont *font3 = [NSFont systemFontOfSize:[NSFont systemFontSize]];<br />NSDictionary *dict3 = [NSDictionary dictionaryWithObject:font3 forKey:NSFontAttributeName];<br />NSMutableAttributedString *line3 = [[NSMutableAttributedString alloc] initWithString:string3 attributes:dict3];<br /><br />NSMutableAttributedString* full = [[NSMutableAttributedString alloc] initWithAttributedString:line1];<br />[full appendAttributedString:line2];<br />[full appendAttributedString:line3];<br /><br />return full;<br /><br /><br />}<br /><br />@end<br />
    



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