Le contenu de ton textView, tu le sauvegardes dans un fichier ou non ?
Si oui et que tu sauvegarde avec la méthode string, c'est normal que tu perdes tous les attributs, il faut utiliser une méthode qui conserve les attributs comme RTFFromRange: je crois ...
<br />textView.setString("apple.com");<br />textView.textStorage().addAttributeInRange(NSAttributedString.LinkAttributeName,"http://apple.com", new NSRange(0,9));<br />textView.textStorage().addAttributeInRange(NSAttributedString.ForegroundColorAttributeName,NSColor.blueColor(), new NSRange(0,9));<br /><br /><br /> //sauvegarde en RTDF avec : <br />textView.writeRTFDToFile(filename,false);<br />//et chargement par :<br />textView.readRTFDFromFile(filename); <br />
ça marche mais il faut double-cliquer pour ouvrir l'url.
Je n'ai pas essayé, mais TextStorage est un attribedString supportant le NSCoding, donc ça devrait rouler tout seul Il faut donc que tu affectes ce TextStorage à une entrée de ton dico.
J'ai pas de NSdata pour ce textView mais uniquement du "value", p-e parce qu'il n'est pas multi lignes ?? Fais un test et tu verras les propositions dans les bindings.
Superbe exemple, tu t'es bien marré ! merci Pour avoir data dans les bindings, il faut que je coche "allow fonts" pour les attributs du textView, ça m'embête un peu, mon champ doit juste contenir une URL, je veux pas que le mec la mette en gros et dans une police exotique !
Seulement, j'ai un message d'erreur quand j'enregistre : 2004-09-22 14:22:11.009 webmasterMemory[4454] *** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value
depuis que je suis passé de value en data (j'ai pas oublié d'allouer les fonts ds IB)...
Je reviens à la charge. Parce que ça ne marche toujours pas ! J'ai donc mon NSData à la place de Value. Lorsque je quitte le champ concerné, l'url passe bien en "mode url" avec lien.
Presque ça Ta chaine d'attributed string de l'url tu la mets comment dans le texte field ? Avec un NSTransformer dans le cadre d'un binding ? A la volée ? ...
Enfin, j'ai ma fonction citée plus haut : - (void)hiliteAndActivateURLs:(NSTextView*)textView
qui édite la chaine par l'outlet textField...
J'ai l'impression que ta méthode hiliteAndActivateURLs, s'adressant au NSTextStorage directement, n'éveille pas le binding sur la textView. Faudrait y mettre un appel à la texView faisant bien comprendre au binding que le contenu NSData a été modifié et donc que l'attribut ajouté doit être pris en compte.
Pour en avoir le coeur net peux tu voir si la méthode déléguée du NSTextView: - (void)didChangeText est bien appelée APRES que le lien ait été mis en place par ta méthode hiliteAndActivateURLs ?
Je viens de faire un test avec un NSLog, elle est bien appelée ! En fait, quand je change de first responder, l'url se souligen bien, mais si je change de site et que je clique sur un autre puis sur celui là , elle ne l'est plus, bref, ça mémorise pas comme tu l'as souligné.
Bon, en mettant l'espace en passant par la méthode de NSTextView on doit forcer le binding à reconnaitre qu'il y a eu changement et à le sauvegarder (et l'attribut lien avec).
Il semble que la communication entre le TextStorage qui prévient son TextView du changement de son contenu ne soit pas pris en compte par le KVO.
Il reste à trouver une méthode plus élégante pour provoquer ce "rafraichissement" du binding sur le NSData. En attendant, si l'espace final te gène, tu peux essayer de virer le dernier caractère de ton URL construit avec le NSStorage puis le rajouter par la méthode de NSTextView: insertText.
ça n'a rien à voir avec une déficience de notification textStorage-textView !!
J'avais pas prété attention à la méthode déléguée que tu utilisais !! En fait tu utilises textDidEndEditing de la classe NSText !!! Donc quand tu ajoutes l'attribut lien à ton texte, la notification de fin d'édition est déjà partie et le binding a DEJA sauvegardé cette modification !! (le texte tapé)
Après, avec ta méthode hiliteMachinTruc tu crée et ajoute l'attribut lien mais SANS passer par une édition de la TextView ==> Le binding ne voit rien !
Essaies donc avec la méthode déléguée (de NSText également) - (BOOL)textShouldEndEditing:(NSText *)textObject Dans laquelle, après mise en place de l'attribut lien, tu dois renvoyer YES. C'est alors que le didEndEditing sera envoyé à son tour provoquant la mise à jour du NSData AVEC le nouvel attribut lien. Notes que cette méthode déléguée reçoit la NSText comme argument, tu peux donc te passer d'un outlet pointant sur la TextView (sous classe de NSText). 8)
Essaies ça (entre 2 essais sql ) si ça marche pas, j'irais voir de plus près ce qu'il convient de faire.
T'es sûr en revanche que je peux me passer de l'outlet, parce que j'en ai besoin pour ma méthode hiliteMachinTruc... On dirait aussi que je peux me passer de textDidEndEditing....
T'es sûr en revanche que je peux me passer de l'outlet, parce que j'en ai besoin pour ma méthode hiliteMachinTruc... On dirait aussi que je peux me passer de textDidEndEditing....
oui tu peux te passer de textDidEndEditing ... et de l'outlet ici en écrivant simplement:
Ouais, en fait le textObject est un équivalent à un outlet textView ?
En tout cas, bravo !
EDIT : j'ai un warning si je mets textView :
passging arg 1 from incompatible pointer type, d'autre parts, ça ne semble pas la meilleure des solutions parce que j'ai 3 outlets en fait qui doivent subir cette fonction.
Réponses
Le contenu de ton textView, tu le sauvegardes dans un fichier ou non ?
Si oui et que tu sauvegarde avec la méthode string, c'est normal que tu perdes tous les attributs, il faut utiliser une méthode qui conserve les attributs comme RTFFromRange: je crois ...
Et ce que tu dis est loin d'être bête je pense...
Ah ClicCool vient de me dire que les bindings devraient garder les attributs en théorie... ???
ça marche mais il faut double-cliquer pour ouvrir l'url.
Ce que je me demande, c comment je vais enregistrer writeRTFDToFile, sachant que j'ai une méthode d'archivage comme ça:
- (BOOL)saveArraysInDictionarylesGroupes:(NSMutableArray*)theGroups atPath:(NSString*)thePath
{
dicArchivage = [[NSMutableDictionary alloc] init];
[dicArchivage setObject: theGroups forKey: @groupsKey];
[NSArchiver archiveRootObject:dicArchivage toFile:thePath];
[dicArchivage release];
return YES;
}
Et que le TextView est une clé de dictionnaire du tableau theGroups.
Merci de m'éclairer !
Il suffit de binder le NSData du TextView et tou va.
Bon, je vais coder une petite appli avec un Array et une textView attachée à une clef des dico de l'array et je la poste.
Fais un test et tu verras les propositions dans les bindings.
[EDIT] Grilled
C'est sur qu'il faut que le NSData soit exposé par ton NSTextFiel pour que ça marche.
Value renvoie une simple string ...
[Fichier joint supprimé par l'administrateur]
Pour avoir data dans les bindings, il faut que je coche "allow fonts" pour les attributs du textView, ça m'embête un peu, mon champ doit juste contenir une URL, je veux pas que le mec la mette en gros et dans une police exotique !
- (void)setUsesFontPanel:(BOOL)flag
Pour interdire que le fontPanel influe sur ta TextView particulière.
J'ai bindé comme ça :
Seulement, j'ai un message d'erreur quand j'enregistre :
2004-09-22 14:22:11.009 webmasterMemory[4454] *** -[NSCFDictionary setObject:forKey:]: attempt to insert nil value
depuis que je suis passé de value en data (j'ai pas oublié d'allouer les fonts ds IB)...
Je reviens à la charge. Parce que ça ne marche toujours pas !
J'ai donc mon NSData à la place de Value. Lorsque je quitte le champ concerné, l'url passe bien en "mode url" avec lien.
Voilà le code :
Et bien sûr :
J'enregistre, je quitte, je reviens, et l'url est en mode texte "classique". C'est fou !
Allé, je suis sûr que tu peux le faire. ;-)
Quand tu installe ton url stylisée dans ton TextView, tu passes bien par les accesseurs ?
///////////////////////
//METHODES ACCESSEURS//
///////////////////////
- (NSMutableDictionary *)dicWebsites
{
return dicWebsites;
}
- (void)setWebsites: (NSMutableDictionary *)w
{
[w retain];
[dicWebsites release];
dicWebsites = w;
}
Ta chaine d'attributed string de l'url tu la mets comment dans le texte field ?
Avec un NSTransformer dans le cadre d'un binding ?
A la volée ? ...
[websiteURL bind: @data toObject: websitesController withKeyPath:@selection.dicWebsites.url options:nil];
[websiteURL bind: @editable toObject: editableController withKeyPath:@selection.websiteEditable options:nil];
- (void)hiliteAndActivateURLs:(NSTextView*)textView
qui édite la chaine par l'outlet textField...
J'ai l'impression que ta méthode hiliteAndActivateURLs, s'adressant au NSTextStorage directement, n'éveille pas le binding sur la textView.
Faudrait y mettre un appel à la texView faisant bien comprendre au binding que le contenu NSData a été modifié et donc que l'attribut ajouté doit être pris en compte.
En fait, quand je change de first responder, l'url se souligen bien, mais si je change de site et que je clique sur un autre puis sur celui là , elle ne l'est plus, bref, ça mémorise pas comme tu l'as souligné.
Histoire de faire réagir le binding pour mise à jour du NSData bindé.
Si ça marche, on essaiera de trouver + élégant, t'inquiètes pas pour ça c'est juste un test
Je comprends pas, ça devrait marcher alors non ?
Au fait, cette méthode était faite, mais j'ai du mal à discerner l'avantage du NStextStorage par rapport à NSMutableAttributedString...
Il semble que la communication entre le TextStorage qui prévient son TextView du changement de son contenu ne soit pas pris en compte par le KVO.
Il reste à trouver une méthode plus élégante pour provoquer ce "rafraichissement" du binding sur le NSData.
En attendant, si l'espace final te gène, tu peux essayer de virer le dernier caractère de ton URL construit avec le NSStorage puis le rajouter par la méthode de NSTextView: insertText.
Le premier qui trouve mieux fait signe ici
ça n'a rien à voir avec une déficience de notification textStorage-textView !!
J'avais pas prété attention à la méthode déléguée que tu utilisais !!
En fait tu utilises textDidEndEditing de la classe NSText !!!
Donc quand tu ajoutes l'attribut lien à ton texte, la notification de fin d'édition est déjà partie et le binding a DEJA sauvegardé cette modification !! (le texte tapé)
Après, avec ta méthode hiliteMachinTruc tu crée et ajoute l'attribut lien mais SANS passer par une édition de la TextView ==> Le binding ne voit rien !
Essaies donc avec la méthode déléguée (de NSText également)
- (BOOL)textShouldEndEditing:(NSText *)textObject
Dans laquelle, après mise en place de l'attribut lien, tu dois renvoyer YES.
C'est alors que le didEndEditing sera envoyé à son tour provoquant la mise à jour du NSData AVEC le nouvel attribut lien.
Notes que cette méthode déléguée reçoit la NSText comme argument, tu peux donc te passer d'un outlet pointant sur la TextView (sous classe de NSText). 8)
Essaies ça (entre 2 essais sql )
si ça marche pas, j'irais voir de plus près ce qu'il convient de faire.
ça a l'air de marcher...
- (BOOL)textShouldEndEditing:(NSText *)textObject {
[self hiliteAndActivateURLs:maTV];
return YES;
}
T'es sûr en revanche que je peux me passer de l'outlet, parce que j'en ai besoin pour ma méthode hiliteMachinTruc... On dirait aussi que je peux me passer de textDidEndEditing....
oui tu peux te passer de textDidEndEditing ... et de l'outlet ici en écrivant simplement:
- (BOOL)textShouldEndEditing:(NSText *)textObject {
[self hiliteAndActivateURLs:textObject ];
return YES;
}
En tout cas, bravo !
EDIT : j'ai un warning si je mets textView :
passging arg 1 from incompatible pointer type, d'autre parts, ça ne semble pas la meilleure des solutions parce que j'ai 3 outlets en fait qui doivent subir cette fonction.