Développement Mac et iPhone
À force de jouer avec le générateur, quelque chose me chagrine: un nouvel utilisateur ne saurait même pas qu'il peut agir sur la vue à la souris. Nous allons donc modifier son pointeur pour apporter cette information.
Voici le fonctionnement que j'attends:
Je vais déjà vous expliquer comment fonctionne ce système de curseurs sous Cocoa, la doc d'Apple me semblant assez indigeste pour quelque chose d'aussi simple.
La classe NSCursor dispose d'un ensemble de méthodes de classes qui renvoient un nouvel NSCursor, ayant des apparences diverses (croix, main, flèches, etc.). Fixer le pointeur est aussi simple que ceci:
[[crosshairCursor] set];
Qui donnera une apparence de croix au pointeur.
Cependant, NSCursor possède un mécanisme plus élaboré, basé sur une pile:
C'est ce mécanisme que nous allons utiliser, puisqu'il nous simplifie la vie, en mémorisant dans quel état il faut remettre le curseur.
Il nous faut surveiller l'appui sur la touche Contrôle:
- (void)flagsChanged:(NSEvent *)theEvent
{
if(pointeurDansLaVue)
{
-[NSResponder flagsChanged:]
est appelée dès qu'une touche spéciale est appuyée, que le pointeur soit dans la vue ou non.
J'ai donc créé une variable d'instance pointeurDansLaVue
. Nous fixerons sa valeur dans les méthodes indiquant l'entrée ou la sortie du pointeur de la vue.
if([theEvent modifierFlags] & NSControlKeyMask)
On regarde si la touche Contrôle est appuyée.
[[NSCursor resizeUpDownCursor] push];
On change le curseur (en mémorisant l'ancien).
else
[NSCursor pop];
Sinon, Contrôle n'est plus appuyée: il faut rétablir le curseur précédent.
}
}
Il faut également rajouter ce code:
- (BOOL) acceptsFirstResponder
{
return YES;
}
Autrement, nous ne recevrions pas les événements clavier.
Cocoa propose de surveiller la position du pointeur par le biais de la classe NSTrackingArea, qui représente un rectangle de la vue. Ajoutons les variables d'instance:
@interface CFRFractalView : NSView {
IBOutlet CFRMandelbrotRender* render;
NSTrackingArea* trackingArea;
BOOL pointeurDansLaVue;
}
Et initialisons-les:
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self)
{
trackingArea = nil;
pointeurDansLaVue = NO;
}
return self;
}
Apple conseille de créer les tracking areas lorsque la vue est insérée dans la fenêtre:
- (void)viewDidMoveToWindow
{
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:(NSTrackingMouseEnteredAndExited
| NSTrackingInVisibleRect | NSTrackingActiveInKeyWindow)
owner:self
userInfo:nil];
Nous fournissons à la méthode d'initialisation:
NSTrackingMouseEnteredAndExited
indique que nous voulons que les méthodes -mouseEntered:
et -mouseExited:
soient appelées lors de l'entrée, respectivement de la sortie du pointeur.NSTrackingInVisibleRect
nous permet de ne pas nous préoccuper de redimensionner la tracking area.NSTrackingActiveInKeyWindow
dit de ne surveiller le pointeur que quand la fenêtre est active.owner
est le propriétaire de la tracking area. Il est possible de déléguer cette gestion, mais ici c'est notre vue qui s'en occupe.userInfo
permet de passer des informations à l'intérieur du NSEvent
reçues par les méthodes d'événement. Inutile pour nous.[self addTrackingArea:trackingArea];
}
Nous associons ensuite la tracking area à la vue.
- (void)mouseEntered:(NSEvent *)theEvent
{
[[NSCursor openHandCursor] push];
pointeurDansLaVue = YES;
}
Quand le pointeur entre dans la vue, nous changeons le curseur en une main ouverte, et mettons à jour pointeurDansLaVue
, nécessaire à la méthode -flagsChanged:
décrite plus haut.
- (void)mouseExited:(NSEvent *)theEvent
{
pointeurDansLaVue = NO;
[NSCursor pop];
}
Quand le pointeur sort de la vue, nous rétablissons le curseur précédent, a priori la flèche normale.
- (void)mouseUp:(NSEvent *)theEvent
{
[NSCursor pop];
}
Lorsque le bouton de la souris est relâché, nous rétablissons le curseur précédent.
Pour les clics:
- (void)mouseDown:(NSEvent *)theEvent
{
Lors d'un clic…
if([theEvent modifierFlags] & NSControlKeyMask)
{
… si la touche Contrôle est appuyée…
[[NSCursor resizeUpDownCursor] push];
Utiliser un curseur en formes de doubles-flèches. À vrai dire, ce curseur est déjà le curseur actuel (puisque la touche Contrôle a été enfoncée avant le clic), mais cet appel permet de contrebalancer le [NSCursor pop]
de la méthode -mouseDown:…
}
else
{
[[NSCursor closedHandCursor] push];
… appel lui même nécessaire pour contrebalancer cet appel à adopter un curseur en main fermée.
}
}
Nous en avons fini avec ces histoires de curseurs. Je vous accorde que ça semble un peu bricolé, mais on ne peut guère faire autrement.
Il n'y a plus qu'à essayer: ça fait tout de suite beaucoup plus pro !
La classe NSTrackingArea fut introduite avec Mac OS 10.5. Autrefois, on utilisait le mécanisme des tracking rectangles, qui est similaire mais plus compliqué à mettre en œuvre. Toujours est-il que nous perdons la compatibilité avec les anciens systèmes, alors prévenons leurs utilisateurs avec un joli message d'erreur. Pour cela:
</dict>
finale, insérez:<key>LSMinimumSystemVersion</key>
<string>10.5.0</string>
À bientôt pour la suite.
Le projet XCode complet à télécharger.
Renaud Pradenc
Céroce.com