Utiliser une Toolbar pour les préférences d'une application

ChachaChacha Membre
décembre 2005 modifié dans Objective-C, Swift, C, C++ #1
Salut,
Je me suis penché sur le problème de faire de zoulies préférences, utilisant une toolbar pour séparer les différentes parties, comme dans iTunes. Il s'agit donc d'une utilisation limitée d'une NSToolbar. Ici, pas de mise à  jour dynamique, mais c'est vraiment très chouette.
Je vous livre le code que j'utilise; il n'est pas forcément parfait, mais ça peut donner des idées.

1) Dans interface builder, dans le NIB de vos préférences, vous avez une fenêtre principale (qui sera la [self window] du controller, (lequel controlleur s'appellera ici PreferencesController))
2) Dans ce NIB, créez autant de NSView que vous voulez de panneaux pour vos préférences (genre un panneau "préférences générales", un panneau "préférences avancées...". Conseil : faites-les de la même largeur. Par contre, pour la hauteur (et c'est tout l'intérêt de ce code) pas de contraintes.
3)créez aussi une vue vide, appelons-la "emptyView". Cette vue servira à  la transition d'un panneau à  l'autre
3)Dans le PreferencesController.h, faites des IBOutlet vers ces vues et connectez-les

Maintenant, le code:
Dans PreferencesController.h

<br />extern NSString* GeneralToolbarItemIdentifier;    //les identifiants des futurs items de la toolbar<br />extern NSString* AdvancedToolbarItemIdentifier; // ici j&#39;en ai mis deux : un pour général, un pour avancé<br /><br />@interface PreferencesController : NSWindowController {<br /><br />  IBOutlet NSView*        generalView;    //un des panneaux de préférences<br />  IBOutlet NSView*        advancedView; //un autre<br />  IBOutlet NSView*        emptyView;     //celui-là , c&#39;est pour la transition d&#39;un panneau à  l&#39;autre<br />  NSMutableDictionary*    toolbarItems; //stockera les items de la toolbar en fonction de l&#39;identifiant<br />}<br /><br />-(IBAction) toolbarHit:(id)sender; //sera appelé lors d&#39;un click sur un élément de la toolbar, pour sélectionner un des panneaux<br />@end<br />


Dans PreferencesController.m :
<br />NSString* GeneralToolbarItemIdentifier     = @&quot;GeneralToolbarItem&quot;;<br />NSString* AdvancedToolbarItemIdentifier    = @&quot;AdvancedToolbarItem&quot;;<br /><br />@implementation PreferencesController<br /><br />-(id) init<br />{<br />  if (![super initWithWindowNibName:@&quot;Preferences&quot;])<br />    return nil;<br />  toolbarItems = [[NSMutableDictionary alloc] init];<br />  return self;<br />}<br /><br />-(void) dealloc<br />{<br />  [toolbarItems release];<br />  [super dealloc];<br />}<br /><br />//une méthode du delegate de la toolbar : les items par défaut<br />-(NSArray*) toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar<br />{<br />  return [NSArray arrayWithObjects:GeneralToolbarItemIdentifier, AdvancedToolbarItemIdentifier, nil];<br />}<br /><br />//une méthode du delegate de la toolbar : les items autorisés : ici ce sont tous nos items par défaut<br />-(NSArray*) toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar<br />{<br />  return [self toolbarDefaultItemIdentifiers:toolbar];<br />}<br /><br />//une méthode du delegate de la toolbar : les items sélectionnables : ici ce sont tous nos items par défaut<br />-(NSArray*) toolbarSelectableItemIdentifiers:(NSToolbar*)toolbar<br />{<br />  return [self toolbarDefaultItemIdentifiers:toolbar];<br />}<br /> <br />//création des toolbarItems à  la volée<br />- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag<br />{<br />  //on commence par regarder si l&#39;item n&#39;a pas déjà  été créé<br />  NSToolbarItem* item = [toolbarItems objectForKey:itemIdentifier];<br />  if (!item) //s&#39;il n&#39;a pas déjà  été créé, on le crée<br />  {<br />    item = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier] autorelease];<br />    <br />    NSString* label = nil; //pour stocker le label de l&#39;item<br />    NSString* imagePath = nil; //pour stocker l&#39;icone (que vous aurez mise dans les resources)<br />    if ([itemIdentifier isEqualToString:GeneralToolbarItemIdentifier])<br />    {<br />      imagePath = [[NSBundle mainBundle] pathForResource:@&quot;generalToolbarItem&quot; ofType:@&quot;tiff&quot;];<br />      label = NSLocalizedString(@&quot;General&quot;, @&quot;General&quot;);<br />    }<br />    else if ([itemIdentifier isEqualToString:AdvancedToolbarItemIdentifier])<br />    {<br />      imagePath = [[NSBundle mainBundle] pathForResource:@&quot;advancedToolbarItem&quot; ofType:@&quot;tiff&quot;];<br />      label = NSLocalizedString(@&quot;Advanced&quot;, @&quot;Advanced&quot;);<br />    }<br />    [item setLabel:label];<br />    [item setImage:[[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease]];<br /><br />    [item setTarget:self];<br />    [item setAction:@selector(toolbarHit:)];<br />    [toolbarItems setObject:item forKey:itemIdentifier];<br />  }<br />  return item;<br />}<br /><br />//quand on clique sur un item de la toolbar, afficher le panneau<br />-(IBAction) toolbarHit:(id)sender<br />{<br />  NSView* view = nil;<br />  NSString* itemIdentifier = [sender itemIdentifier];<br /><br />  //on choisit la vue à  afficher<br />  if ([itemIdentifier isEqualToString:GeneralToolbarItemIdentifier])<br />    view = generalView;<br />  else if ([itemIdentifier isEqualToString:AdvancedToolbarItemIdentifier])<br />    view = advancedView;<br /><br />  //calcul de la prochaine taille du contenu de la fenêtre<br />  NSWindow* window = [self window];<br />  NSView*   contentView = [window contentView];<br />  NSRect oldContentFrame = contentView ? [contentView frame] : NSMakeRect(0, 0, 0, 0);<br />  NSRect newContentFrame = [view frame];<br /><br />  //en fonction de la future taille, il faudra redimensionner la fenêtre, et la déplacer aussi (pour garder le &quot;top-left point&quot; à  la même place)<br />  NSRect newFrame = [window frame];<br />  newFrame.size.width  += (newContentFrame.size.width  - oldContentFrame.size.width);<br />  newFrame.size.height += (newContentFrame.size.height - oldContentFrame.size.height);<br />  newFrame.origin.y    -= (newContentFrame.size.height - oldContentFrame.size.height);<br /><br />  //on va virer la contentView de la fenêtre. Pour éviter qu&#39;elle soit détruite, on fait un retain dessus<br />  [[window contentView] retain];<br /><br />  //lors du redimensionnement de la fenêtre, on utilise la emptyView pour éviter de démolir nos vues &quot;generalView&quot; et &quot;advancedView&quot;<br />  [emptyView setFrame:newContentFrame];<br />  [window setContentView:emptyView];<br />  [window setFrame:newFrame display:YES animate:YES];<br /><br />  //maintenant que la fenêtre a la bonne taille, on peut y mettre la vue désirée<br />  [[window contentView] retain];<br />  [window setContentView:view];<br />}<br /><br />//au chargement du controlleur, il faut créer la toolbar et choisir le panneau initial<br />-(void) awakeFromNib<br />{<br />  NSToolbar* toolbar = [[NSToolbar alloc] initWithIdentifier:@&quot;preferencesToolbar&quot;];<br />  [toolbar setDelegate:self];<br />  NSWindow* window = [self window];<br />  [window setToolbar:toolbar];<br />  [window setShowsToolbarButton:NO];//ici, il vaut mieux ne pas pouvoir masquer la toolbar<br />  [toolbar setSelectedItemIdentifier:GeneralToolbarItemIdentifier];<br />  [self toolbarHit:[toolbarItems objectForKey:[toolbar selectedItemIdentifier]]];<br />  [toolbar release];<br />}<br /><br />


Voilà , j'espère que ça pourra vous servir !

+
Chacha

Réponses

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