Charger des menu déroulants popup

muqaddarmuqaddar Administrateur
19:06 modifié dans API AppKit #1
Salut,

Je voulais savoir pour quelle technique vous optiez dans vos programmes pour charger des menus popup avec disons 200 lignes.
Simple tableau ? Fichier texte (plus facile à  mettre à  jour), si oui, sous quelle forme et format ?

merci
«1

Réponses

  • cbrandtcbrandt Membre
    19:06 modifié #2
    tout dépend du contexte...

    dans un de mes projets, il s'agit d'une petite liste gérée par les préférences, et le NSPopupButton est rempli avec [NSPopupButton addItemsWithTitles: (NSArray*) titles].

    dans un autre projet, je le remplis avec le contenu (filtré) d'un répertoire, en utilisant [NSPopupButton addItemsWithTitle: (NSString*) title] si l'item me convient...

    maintenant, si tu as 200 lignes, un NSTableView ne serait-il pas plus adapté pour afficher le contenu ?
  • muqaddarmuqaddar Administrateur
    19:06 modifié #3
    En fait, j'ai pensé à  un NSTableView, mais par manque de place je ne peux en mettre un (en plus y'en a déjà  un à  côté).
    Mais je me suis mal exprimé, en fait, je vais gérer la liste ds un tableview ds les prefs et là  j'activerai ou pas des lignes de cette liste. Le résultat des lignes activées arrivera dans le popup ensuite.

    Mais supposons que je veuille vraiment importer ds un popup ou un tableView une liste d'un fichier texte, quel doit être le format de ce dernier pour gérer accents, espaces...etc ? Et qu'on ait un élément par ligne...
  • cbrandtcbrandt Membre
    19:06 modifié #4
    si tu mets un élément par ligne dans un fichier texte, utilise [NSString componentsSeparatedByString: (NSString*) string] pour décomposer une nsstring en nsarray selon une chaà®ne qui sert de séparateur (ici @\n, qui est la fin de ligne).
    cet nsarray peut ensuite être utilisé dans le datasource de la nstableview ou pour remplir le nspopupbutton:

    <br />[monPopup addItemsWithTitles: [[NSString stringWithContentsOfFile: @&quot;chemin&quot;] componentsSeparatedByString: @&quot;&#092;n&quot;]];<br />
    
  • muqaddarmuqaddar Administrateur
    19:06 modifié #5
    Ah oui, pas bête.:-)
    Merci cbrandt.

    Sinon, le fichier texte doit avoir une extension ? txt ? autre ?
  • cbrandtcbrandt Membre
    19:06 modifié #6
    l'extension du fichier n'a aucune importance...

    concernant un de tes posts précédents concernant les accents, si par exemple le fichier texte vient d'un pc windows, tu peux essayer quelque chose comme ça:

    <br />NSData *data;<br />NSString *string;<br />NSArray *array;<br /><br />data = [NSData dataWithContentsOfFile: @&quot;chemin fichier&quot;];<br />string = [[NSString alloc] initWithData: data encoding: NSISOLatin1StringEncoding];<br />array = [string componentsSeparatedByString: @&quot;&#092;n&quot;];<br />
    


    NSISOLatin1StringEncoding est à  adapter en fonction de l'origine du fichier. Si le fichier a été créé avec [NSString writeToFile:atomically:] tu n'en a bien sûr pas besoin et tu utilises la version de mon post précédent; de même si tu crées le fichier dans TextEdit, enregistré avec un codage Unicode...
  • muqaddarmuqaddar Administrateur
    19:06 modifié #7
    Bon, je vais tester ça très prochainement.

    Merci pour toutes ces précisions !
  • cbrandtcbrandt Membre
    19:06 modifié #8
    y'a pas de quoi !
  • 19:06 modifié #9
    dans 1100082559:

    En fait, j'ai pensé à  un NSTableView, mais par manque de place je ne peux en mettre un (en plus y'en a déjà  un à  côté).


    S'il y a 200 entrées, il vaut mieux mettre un ComboBox, avec une option d'autocomplétion, c'est assez pénible les menus à  plus de 20 entrées.... En plus les ComboBox peuvent avoir un datasource, ce qui rend particulièrement facile la synchronisation entre la table et le champ.
  • muqaddarmuqaddar Administrateur
    novembre 2004 modifié #10
    Bein en fait, ça peut aller jusqu'à  200 entrées, mais y'en aura rarement plus de 20 en même temps.

    En fait, c'est quoi les principales différences entre comboBox et popup, mis à  part l'auto-complétion ?

    Et on peut mettre une image à  côté des entrées d'un combo box ?
  • novembre 2004 modifié #11
    Le combo n'oblige pas à  se servir de la souris. Il suffit de taper le texte... Dans le popUp on est obligé d'ouvrir un menu, et le sélectionner. Et autre élément important, quand tu navigues avec la touche tab parmi les contrôles, tu peux atteindre un combo et pas un popup.

    De toute façon, même s'il y en a 20, c'est déconseillé... J'aurais même tendance à  dire que si on peut en avoir 200, tu dois penser l'interface pour que la personne qui en a 200 puisse être à  l'aise. (En plus la navigation dans un menu est particulièrement lente sur les petites configs quand il y a beaucoup d'éléments ...surtout quand il y a des images)

    Même s'il est précisé qu'on peut les utiliser à  la place d'une liste, l'utilisateur qui fait tout à  la souris n'est pas gêné par les combo (et c'est même mieux, car ce n'est pas un menu, mais une tableview qui est affichée, donc la navigation est plus facile), et celui qui préfère le clavier sera gêné par les PopUps...

    On ne peut pas mettre d'image dans un combo (normal c'est une classe qui hérite de NSTextField...). À toi de voir si tu préfères le cosmétique ou le fonctionnel... (en attendant de sous classer NSComboBox :P)

    Don't use pop-up menus:
    - For more than 12 items; use a scrolling list unless space is restricted
    - When the number of items in the list can change
  • 19:06 modifié #12
    dans 1100082559:

    Mais supposons que je veuille vraiment importer ds un popup ou un tableView une liste d'un fichier texte, quel doit être le format de ce dernier pour gérer accents, espaces...etc ? Et qu'on ait un élément par ligne...


    La question des accents et autres caractères spéciaux n'est pas une limitation du format, mais plutôt une de l'encodage. Si tu fais un fichier texte, fais le en unicode...
  • muqaddarmuqaddar Administrateur
    19:06 modifié #13
    Et bien merci encore pour toutes ces infos !
    Me voilà  moins bête maintenant. 

    Je vais certainement opter pour la combo.  :trinque:
  • muqaddarmuqaddar Administrateur
    19:06 modifié #14
    Bon, j'ai fait un test et malheureusement, il ne charge rien :

    <br />NSString* paysPath;<br />paysPath = [[NSBundle mainBundle] pathForResource:@&quot;Pays&quot; ofType:@&quot;txt&quot;];<br />NSArray* test = [[NSString stringWithContentsOfFile: @&quot;paysPath&quot;] componentsSeparatedByString: @&quot;&#092;n&quot;];<br />
    


    Qd je NSLog le tableau test, il est vide. Le fichier Pays est en Unicode...
  • mpergandmpergand Membre
    19:06 modifié #15
    Salut oxitan,

    Pour ton problème de chargement je ne sais pas, peut-être un mauvais chemin.
    Ce que je voulais te signaler, c'est que le dossier Resources n'est pas le bon endroit pour y mettre un ficher suceptible d'être modifié (c'est ton cas si j'ai bien compris) car le prg peut-être démarré d'un CD ou d'un volume/dossier en lecture seule.
  • muqaddarmuqaddar Administrateur
    19:06 modifié #16
    Ok mpergand.

    Mais ce fichier ne pourra être modifié en fait.
    En revanche, j'en ai d'autres qui le seront et je les mettrai dans le dossier User soit ds les documents (un dossier pour mon app), soit ds Application Support.
  • mpergandmpergand Membre
    19:06 modifié #17
    A bon ?

    Je voulais savoir pour quelle technique vous optiez dans vos programmes pour charger des menus popup avec disons 200 lignes.
    Simple tableau ? Fichier texte (plus facile à  mettre à  jour)


    Du coup, je comprends pas bien l'interêt d'utiliser un fichier texte plutôt qu'un NSArray de string ???
  • muqaddarmuqaddar Administrateur
    novembre 2004 modifié #18
    Bah, c'est plus facile à  remplir et éditer un simple fichier texte à  part non ?

    De plus, il y aura des versions localisées de ce fichier.
  • mpergandmpergand Membre
    19:06 modifié #19
    OK, tu trouve plus simple de modifier un fichier texte plutôt que de modidier un tableau dans le source, bon, si tu veux.


    De plus, il y aura des versions localisées de ce fichier

    Justement c'est la question que je me posais.

    Puisque tu as un tableau static, des fichiers .strings classiques conviennent parfaitement pour la localisations. Les termes utilisées dans ton fichier texte seront-ils uniques, apparaitront-ils ailleurs dans ton appli ? (localisation en double?)

    Bon , je chippote un peu, les fichiers textes ça marche aussi ;)
  • muqaddarmuqaddar Administrateur
    19:06 modifié #20
    Non, tu as raison, c'est très intéressant tout ça. :)

    En fait, je veux écrire la liste de 200 pays dans mon fichier et charger cette liste dans les prefs de l'appli dans un tableView, et là , activer par défaut une vigntaine de pays qu'on retrouvera dans un popup dans l'appli. Ce fichier initial est susceptible d'être modifié (par moi uniquement), et c'est pour faciliter son éventuelle mise à  jour que je voulais mettre ces pays dans un fichier texte.
    Maintenant, mon soucis est de localiser au moins en anglais cette liste de pays, pour le nib anglais. Et là , je m'interroge, je voulais faire effectivement un autre fichier avec les noms des pays en anglais et le charger qd le nib anglais est chargé. Mais y'a p-e plus simple ou mieux ? Avec un fichier de strings, cela me paraà®t plus galère non ?
  • 19:06 modifié #21
    À partir du moment où tu localises, le simple tableau ne suffit pas... Pour la bonne et simple raison que l'ordre des pays changera d'une localisation à  une autre. Et supposons qu'un italien utilise ton prog et que la mise à  jour apporte une version italienne, il est foutu...

    Donc une solution est d'avoir pour chaque pays un tableau à  deux éléments: un identifiant unique qui ne change pas suivant les localisations, et le nom du pays.

    Pour ce qui est du dossier par défaut:

    Resource Management


    Here are some tips to help you manage your bundle?s resource files:

    Include all required resources inside your application bundle. Your application bundle should always have everything it needs in order to run.


    Include only the specific subset of files that require localization in your bundle?s language-specific resource directories. If a resource does not require localization, there is no need to create extra copies of it. The bundle-loading code checks for global resources as well as localized resources and returns the one that is most appropriate.


    Use an installer to place optional resources in the appropriate Library subdirectory of the user?s system. Optional resources are things like document templates or other resources that are useful to an application but not required for it to launch. Most application-related files should go in an application-specific subdirectory of ~/Library/Application Support or /Library/Application Support. See The Mac OS X File System in Mac OS X Documentation for information on where to install files.
  • muqaddarmuqaddar Administrateur
    19:06 modifié #22
    dans 1100177424:

    Donc une solution est d'avoir pour chaque pays un tableau à  deux éléments: un identifiant unique qui ne change pas suivant les localisations, et le nom du pays.


    Je dirais même plus : 3 élements avec une clé image du drapeau lié. ;)
    L'identifiant pourrait être une courte chaine de caractères ou un nombre ?
    Quand au drapeau associé, il pourrait prendre le nom de l'identifiant, il n'y aurait plus qu'à  tous les mettre ds le bundle et de les charger ds la tableview avec NSImage.
    Il ne me reste donc plus qu'à  construire un fichier plist avec les 3 clés et mes enresgistrements.

    J'ai bon ?
  • 19:06 modifié #23
    Le nombre aurait été intéressant s'il s'agissait du critère de tri, ce qui n'est pas le cas. Donc il vaut mieux la chaine de caractère, qui comme tu l'as dis peut servir à  avoir le fichier du drapeau. Donc 2 clés suffisent...
  • muqaddarmuqaddar Administrateur
    19:06 modifié #24
    Me revoilà .

    J'ai un soucis de "logique" avec mon fichier plist.
    Dans les prefs, je vais chercher ce fichier qui contient les noms de pays et leurs clés. Je voulais le mettre dans le bundle de l'appli. Or, dans les prefs et ma tableView qui liste ces pays, il y a un champ checkBox pour activer ou pas les pays. Par défaut, une vingtaine sera activée. Seulement, cet "état" doit être enregitré quelque part. La logique voudrait que je l'enregistre dans le même fichier or il est dans le bundle... Sauf si je le mets dans une Library du sytem (du dossier user). Mais dans ce cas, il faut le mettre à  l'installation de l'appli et donc de créer un installeur ? Bon, je patauge un peu alors qu'il y a sûrement quelque chose de simple à  faire. Enregistrer l'état des preferences dans un autre fichier, lui même bien dans le dossier Application Support du User ? Cela implique de reprendre les clés du fichier plist livré avec le bundle ?
    Que de questions !
  • 19:06 modifié #25
    Tu peux mettre en code les id des pays sélectionné par défaut quand les prefs sont vide. Au démarrage, il vérifie l'existence de la préférence et crée l'entrée ad hoc si nécessaire.
  • muqaddarmuqaddar Administrateur
    19:06 modifié #26
    Back.

    Et comment faire pour connaà®tre la langue sélectionnée dans le système ? Cette langue choisit les bons nibs automatiquement, mais il faut que je la connaisse pour choisir les bons fichiers ressources et les copier dans Application Support au démarrage de l'appli.
    merci.
  • Eddy58Eddy58 Membre
    19:06 modifié #27
    La classe NSBundle comporte des méthodes pour recueillir des infos sur la localisation, peut-être peut tu passer par là  ? :)
  • mpergandmpergand Membre
    novembre 2004 modifié #28
    J'utilise ça:
    <br />public static boolean IsFrenchLocalization()<br />  {<br />  NSBundle mainBundle=NSBundle.mainBundle();<br />  NSArray localArray=mainBundle.preferredLocalizations(mainBundle.localizations());<br />  String localStr=(String)localArray.objectAtIndex(0);<br />  return localStr.equals(&quot;French&quot;);<br />  }
    


    Une autre solution serait de définir un mot clef dans les fichiers .string, ex:

    CLEF_LANGUE="FR";
    et
    CLEF_LANGUE="US";

    et de tester la valeur retournée pour cette clef par localizedString("CLEF_LANGUE")
  • 19:06 modifié #29
    Si tu ne mets que les IDs des pays dans ton AppSupport, ce n'est pas un souci que tu dois avoir.
  • muqaddarmuqaddar Administrateur
    19:06 modifié #30
    dans 1100519057:

    Si tu ne mets que les IDs des pays dans ton AppSupport, ce n'est pas un souci que tu dois avoir.


    J'ai plutôt prévu de copier le fichier pays par défaut dans Application Support et d'éditer ce fichier ensuite, avec une BOOL sur les pays activés (checkbox ds les prefs).
    J'ai l'impression que je merdouille encore dans ma logique. :(

    Il faudrait que ce fichier ne contienne pas le nom localisé du pays mais que l'iD et mon BOOL comme tu dis Renaud, mais que le nom du pays localisé reste dans le bundle.

    Au final, j'ai donc :
    - 1 fichier copié ds App Support et éditable avec paysId et BOOL
    - 2 fichiers langues ds le bundle avec paysId et paysName OU BIEN sous forme de fichier strings ?

  • novembre 2004 modifié #31
    Je maintiens le plus simple, c'est dans app support (ou mieux dans les prefs), un tableau qui ne contient que les ID des pays, pour vérifier si la case est coché, il y a une méthode de NSArray qui est containsObject:. dans le bundle, tu mets un fichiers qui serait par exemple Countries.strings, structuré comme suit:

    &quot;be&quot;=&quot;Belgique&quot;;<br />&quot;fr&quot;=&quot;France&quot;....
    


    Chaque élément de ta liste est stocké dans un dico, chaque info peut être retrouvée à  la clé qui correspond à  l'identifier de la colonne. et tu rajoutes une clé ID (qui ne sera pas affichée dans le tableau), ce qui permet de faire la correspondance entre un nom localisé et et l'ID du pays. Quand tu construis ton dico, tu mets pour la clef name la valeur de NSLocalizedStringFromTable([dict objectForKey:@ID],nil,@Countries);
Connectez-vous ou Inscrivez-vous pour répondre.