Je profite de ce 'thread' dans le forum developpeurs pour parler d'une notion assez importante lorsqu'on développe sous cocoa.
Les frameworks Foundation Kit et Application Kit contiennent un type de 'classes' appelé Protocole.
Un Protocole regroupe un ensemble de methodes. Ces methodes sont tout simplement déclarées mais non implémentées.
On dit d'une classe qui implémente une ou plusieurs méthodes d'un Protocole qu'elle obeît à ce Protocole.
Cette notion existe également dans Java ou elle porte le nom d'interface. je préfère le nom Protocole plus parlant alors que le terme interface est déjà utilisé dans l'orienté objet pour désigner autre chose.
Par exemple lorsque vous créez une nouvelle classe, si vous voulez que des instances de cette classe puissent être cloner (ou copier), vous devez implémenter la méthode
copyWithZone du Protocole NSCopying.
L'interet me direz-vous? Quand vous voyez les classes de cocoa, il y a une rubrique
Conform to pour indiquer le ou les Protocoles satisfaits par les instances de cette classe.
Si une classe MaClasseGenial satisfait au Protocole NSCopying, si je veux avoir un objet B identique à une instance A de cette classe, je code MaClasseGeniale *B=[A copyWithZone:z]
C'est pourquoi lorsque vous publiez vos classes ou les documenter,il faut utiliser le modèle de décalaration des classes d'Apple.
Un très bon exemple de l'utilisation des Protocoles c'est lorsque vous créez une classe de type View dans Interface Builder.
Si vous voulez permettre aux utilisateurs de remplir cette vue avec des images, des couleurs par simple Drag and Drop, votre objet View doit obeïr au Protocole NSDraggingDestination qui signifie qu'elle est la destination (ou la cible) potentielle d'une opération de Drag and Drop.
Une opération de Drag and Drop sous Mac OS X est à la fois simple dans sa réalisation pratique, mais complexe dans son exécution.
En effet elle met en jeu 3 acteurs.
- La source du Drag and Drop,
- La destination
- Le presse papier ou plutôt le serveur de presse-papiers.
En effet sous Mac OS X il existe plusieurs sortes de presse-papiers chacun étant défini par le type d'opération effectuée par un utilisateur.
Ainsi il existe un presse-papier pour les opérations de Drag and Drop, un autre pour les opérations de couper (ou copier)/coller, ...etc.
Apple a également défini un certain nombre de types d'objets qu'un serveur de presse- papier peut avoir dans un presse-papier donné. Cela va d'un contenu de fichier à une chaine de caratères ou une info concernant une police de caratères, ...etc.
En fait dans une opération de Drag and Drop, il y a un dialogue permanent entre le runtime cocoa qui représente grosso modo le serveur de presse-papiers et l'objet destinataire.
Le protocole NSDraggingDestination donne la liste des différents messages reçus par l'objet destination lors de ce dialogue.
Je vais décrire comment se déroule une opération de Drag and Drop ainsi que le dialogue qui s'en suit.
Dans ma description :
- Act désignera l'action de l'utilisateur
- Dest designera le destinataire
- Rt désignera le runtime cocoa et entre " le message qu'il envoie à Dest.
Sachez aussi que les messages envoyés au destinatire ont tous le paramètre sender qui désigne celui qui envoie le message.
D'autre part Il existe un Protocole qui s'appelle NSDraggingInfo qui déclare la liste de messages que le destinataire peut envoyer au sender pour lui poser un certain nombre de questions. Je noterai par Quest une question poser au sender par Dest, et Rep la réponse du sender.
Voici en gros chronologiquement comment cela se passe :
Act : Déplacement d'une image qui chevauche Dest.
Rt : "draggingEntered"
Dest : Quest : c'est quoi le type d'objet que tu veux déposer chez moi? Rep : NSTIFFPboardType (image au formet TIFF).
Parfait je supporte ce type d'objet (une image dans le cas présent). Attention je n'accepte que la copie de l'image (NSDragOperationCopy).
Act : un signet sous le curseur de la souris indique que l'objet drappé est recevable (sinon on a un signet interdit).
Act : l'image est entièrement dans Dest
Rt : "draggingUpdated"
Dest : c'est Ok pour moi je fais quelques vérifications.
Act : l'utilisateur lache l'image sur Dest
Rt : "prepareForDragOperation"
Dest : ok pour moi
Rt : "performDragOperation"
Dest : Quest : passes moi l'image Rep : donne l'image du prese-papier de Drag'n drop.
Dest : je vais l'arranger pour l'adapter à ma taille
Rt : "concludeDragOperation"
Dest : je raffraichi mon affichage et surtout j'envoie au NotificationCenter un message comme quoi j'ai changer mon aspect.
Eh toi l'utilisateur suis pas beau comme ça?
Comme on le voit l'implémentation du drag and drop se résume pour le développeur à implémenter les différents messages de Rt.
L'avantage de ce principe c'est que cette implémentation peut être réutiliser pour une autre classe View de même type.
Dans les outils de développement, Apple fournit un exemple d'implémentation dans dans la classe CompositeView de l'application CompositeLab.
Cette exemple illustre également ce que je disais dans un article précédent.
A savoir qu'une appli sous cocoa c'est des objets qui s'envoient des messages.
Ainsi lorsque vous créez une classe, vous codez les méthodes de votre objet (définies par vous) et ceux des protocoles auxquels vous obeïssez (définies par Apple), et vous déclarez les messages que vous envoyez au NotificationCenter à chaque fois que vous changer votre look.
S'il y a des changements qui méritent réflexion avant de les valider, vous déclarez les messages (avec réponse oui ou non) que vous envoyez à votre délégué.
Ne pas oublier, dans la méthode d'initialisation de votre View d'enregistrer les différents types d'objets que vous acceptez dans une opération de Drag'n drop :
[self registerForDraggedTypes:[NSArray arrayWithObjects:NSColorPboardType,NSTIFFPboardType,nil]].
Encore une preuve de l'efficacité et l'élégance des solutions proposées par cocoa.
A+
[Ce message a été modifié par Manu (edited 26 Novembre 2000).]