[Résolu] Impression "à  la publipostage"

MickMick Membre
septembre 2010 modifié dans API AppKit #1
Bonjour à  tous,

Voilà  mon prolème et je ne sais pas par quel bout le prendre :

J'ai une tableView dont le contenu dépend de la sélection d'un arrayController (lui-même bindé à  une autre tableView, structure classique). L'utilisateur, en changeant la sélection, se voit donc afficher un certain contenu dans ma fameuse tableView.
Maintenant, je cherche à  imprimer un "état"  qui contiendrait autant de copie de la tableView qu'il y a de possibilité de sélection, autrement dit créer une vue imprimable qui contiendrai un certain nombre de fois la table mais avec les contenus différents correspondant à  toutes les sélections possibles.

Ma question : comment commencer pour que ce ne soit pas trop "douloureux" en code ?

Réponses

  • laudemalaudema Membre
    septembre 2010 modifié #2
    dans 1284659142:

    Ma question : comment commencer pour que ce ne soit pas trop "douloureux" en code ?

    Pour avoir essayé (et réussit :), au début c'est quand même un peu douloureux "en code".
    il faut user du NSLayOutManager, des NSTextTable et autre NSTextTableBlock, et il n'y a pas beaucoup de doc (la démo Expenses envoie dans le presse papier sans dessiner !) mais si tu as déjà  fait des tableaux en html c'est assez comparable.
    D'ailleurs dans mes recherches, au début, c'était la solution la plus souvent recommandée, et pourquoi pas après tout.
    Ensuite tu le passes à  une WebView et le tour est joué ..
    Mais bon, j'ai préféré apprendre à  utiliser NSLayoutManager et imprimer ma vue tout seul car le tableau n'était qu'une partie d'un tout et j'apprenais à  imprimer au pixel près sur ma feuille via "drawAtPoint:" ...
    Je venais d'avoir fini quand je suis tombé sur un excellent travail http://themikeswan.wordpress.com/2010/07/31/printing-tabular-data/
    Qui fait une classe avec tout ce qu'il faut pour envoyer les données et récupérer sa table prête à  dessiner dans une NSAttributedString, y' a plus qu'à  ;).
    Je te laisse découvrir, je ne l'ai pas implémenté moi même puisque j'ai ma solution, mais non, avec un peu de persévérance il n'y a rien de si lourd une fois qu'on a compris comment ça marche... Plus le confort de maà®triser bien les choses :)

    Si tu veux quelque chose de vraiment rapide tu essayes de configurer une VueTableau dans IB pour qu'elle ne soit pas trop vilaine sur papier et tu l'ouvres dans Le pdf reader par défaut en laissant la charge de l'impression à  l'utilisateur.
    <br />- (IBAction)printZatBox:(id)sender;{<br />	NSRect boxRectangle = [printBox bounds];<br />	NSData *pdfData = [printBox dataWithPDFInsideRect:boxRectangle];<br />	if (pdfData) {<br />		NSString *path = [[@&quot;/Applications/pyxvital/LOTS&quot; stringByExpandingTildeInPath] stringByAppendingPathComponent:<br />						&nbsp; @&quot;Fichier_Test.pdf&quot;];<br />		NSError *e;<br />		if (![pdfData writeToFile:path<br />						&nbsp; options:0<br />							error:&amp;e])<br />			NSLog(@&quot;Erreur à  l&#39;écriture du fichier %@&#092;nErreur N°: %i&#092;n%@&quot;,<br />				&nbsp; [path lastPathComponent], [e code], [e localizedDescription]);<br />		else <br />			[[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:path]];<br />	}<br />}<br />
    

    Tu peux reprendre la VueTableau ou la ScrollView qui est autour (après l'avoir customisée aussi) ou même une boite dans laquelle tu auras d'autres champs. Tu déclares un IBOutlet NSView *printBox et tu le lies dans IB à  la XXXView que tu veux voir imprimer..

    A toi de voir ce qui t'intéresse, mais à  ma connaissance on en est là ...
  • MickMick Membre
    septembre 2010 modifié #3
    Bonjour,

    Merci pour ton lien, mais j'avoue ne pas comprendre comment fonctionne une NSTextTable.

    De même, comment créer une vue perso qui contiendra n fois ma table avec des données différentes ?
    Pour l'instant j'ai démarré en créant une boucle qui passe en revue ce qui m'intéresse pour créer mes tables, et dans laquelle je compte créer mes NSTableView, mais là  problème : je les remplis comment ?? Normalement, une table est peuplée via une dataSource, mais là  je ne vais pas m'amuser à  créer une datasource pour chaque version de ma table ... si ?

    [EDIT]
    Après décorticage du code de la classe, je crois à  peu près comprendre qu'une textTable peut se peupler manuellement en fait. Je me plonge là -dedans
    [/EDIT]


  • laudemalaudema Membre
    septembre 2010 modifié #4
    Tu as beaucoup plus d'explications dans la page suivante du site de Mike Swan http://themikeswan.wordpress.com/2010/08/05/expenses-part-5-printing-core-data/
    Si tu as déja bouclé sur tes tables tu n'as qu'à  en faire des tableaux de strings et les envoyer à  MSPrintTable pour récupérer une NSAttributedString que tu imprimeras ensuite via une textView créée à  pour l'occasion dans une NSPrintOperation.
    Tu étais prévenu que ce n'était pas si simple que peupler une NSTableView via les bindings ;)
    Par contre une fois qu'on a saisi c'est pas non plus si compliqué, enfin, il m'a semblé.. Et pas non plus des tonnes de code  >:) [EDIT]<= Celui là  je me suis longtemps demandé où on pouvait le caser  :)

    Au cas ou: tu peux juger du résultat de tes impressions en demandant Aperçu dans le dialogue d'impression, ça épargnera quelques bouts d'arbre et un peu d'encre pour des impressions pas forcément destinées à  la postérité ;)
  • MickMick Membre
    13:49 modifié #5
    Pour le EDIT, j'étais persuadé que ça faisait un cadre !
    Bon, je vais un peu galérer pour le MSPrintTable (je suis pas en obj C 2.0 Tiger powerPC...) il faut que j'écrive les accesseurs (@synthetize, bah ça n'existe pas chez moi...)
    Je vais creuser les textTable, je ne vois pas d'autres solutions.

    Merci à  toi Laudema
  • laudemalaudema Membre
    septembre 2010 modifié #6
    dans 1284733269:

    Pour le EDIT, j'étais persuadé que ça faisait un cadre !
    Bon, je vais un peu galérer pour le MSPrintTable (je suis pas en obj C 2.0 Tiger powerPC...) il faut que j'écrive les accesseurs (@synthetize, bah ça n'existe pas chez moi...)
    Je vais creuser les textTable, je ne vois pas d'autres solutions.

    Merci à  toi Laudema

    Hop, un petit coup de main de Xcode: tu vas dans le menu AppleScript (à  côté du menu Aide) et tu descends jusque code après avoir au préalable sélectionné tes variables dans l'interface. Tu le connaissais pas celui là  ?  :)

    Sinon tu n'es pas obligé de tout prendre. Tu dois juste instancier une NSTextTable avec ses attributs et autant de NSTextTableBlock qu'il y a de cellules à  remplir mais tu fais ça dans une boucle à  la html, rien de folichon mais rien d'exceptionnel non plus.
    Si MSTablePrint est trop copieux pour toi tu peux regarder à  ce qu'il y a dans la démo iSpend (fais une recherche dans la doc Xcode) le doc est dans la classe MyDocument_Pasteboard (excuses, hier soir j'avais cité Expenses de mémoire) et regarde la méthode - (NSAttributedString *)attributedStringFromTransactions:(NSArray *)transactions et la méthode qu'elle appelle: addCell.
    Tu pourras revenir à  Mike Swan quand tu voudras regarder comment faire pour imprimer une NSAttributedString ..

  • MickMick Membre
    13:49 modifié #7
    Bonjour,

    En fait je viens enfin de comprendre qu'au bout du compte le but est de créer une NSAttributeString immense, découpée en morceaux, chaque moreceau ayant un attribut NSParagrapheStyle. C'est dans ces paragraphStyle que l'on dit dans quelle(s) cellule(s) le texte doit être en faisant un setTextBlock, et enfin c'est dans le textBlock qu'on associe à  la NSTextTable et à  la bonne colonne/bonne ligne.

    Du coup, j'ai enfin réussit à  construire mes moults tableaux. Le petit soucis, c'est : comment récupérer la taille exacte de la NSTextTable afin de dimensionner correctement une NSTextView ? A l'arrache (en faisant la somme de la taille des colonnes) j'ai réussi à  afficher une table correctement prête à  imprimer, mais je voudrais calculer ça bien...

  • laudemalaudema Membre
    septembre 2010 modifié #8
    Désolé je n'ai que peu de temps à  te répondre ce samedi matin.
    NSAttributedString a une méthode size (dans la catégorie stringAdditions) mais je suis pas certain qu'elle donne de bons résultats pour une table, tu peux toujours l'essayer et les autres méthodes de calculs de taille http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSString_AppKitAdditions/Reference/Reference.html#//apple_ref/doc/uid/20000155

    Mais tu trouveras probablement mieux sur Google.
    [Edit]
    Bingo ?
    http://stackoverflow.com/questions/2282629/how-to-get-height-for-nsattributedstring-at-a-fixed-width
    donne deux liens très intéressants
    http://www.sheepsystems.com/sourceCode/sourceStringGeometrics.html pour une démo d'une catégorie qui permet de faire des calculs de ce type
    http://teilweise.tumblr.com/post/293948288/boundingrectwithsize-options-attributes qui explique que pour faire ça la méthode à  utiliser est donc bien celle de NSAttributedString de NSStringAdditions boundingRectWithSize:options:attributes: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSString_AppKitAdditions/Reference/Reference.html
    en utilisant l'option NSStringDrawingUsesLineFragmentOrigin http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSString_AppKitAdditions/Reference/Reference.html#//apple_ref/doc/c_ref/NSStringDrawingUsesLineFragmentOrigin
  • MickMick Membre
    13:49 modifié #9
    OK !!
    J'ai vu la méthode boundingrectwithsize, mais je ne voyais pas l'intérêt, vu que la méthode demande... un size !!
    Apparemment, il suffit de mettre NSZeroSize !
    Je vais tester ça.

    Merci pour le lien (tu avoueras quand même qu'il faut les trouver les méthodes utiles ! c'est quand même pas super immédiat)

    PS : tu vois que tu as pris goût à  [Edit] !
  • laudemalaudema Membre
    13:49 modifié #10
    dans 1284886932:

    OK !!
    Apparemment, il suffit de mettre NSZeroSize !
    Je vais tester ça.


    Dans mon code à  moi j'ai ça pour calculer la NSSize
    <br />	NSRect otherRect = [firstString boundingRectWithSize:NSMakeSize(0, 0) options:NSStringDrawingUsesFontLeading attributes:attribs];<br />
    


    Mais je ne l'avais pas retrouvé tout de suite, et comme avoir une idée des méthodes disponibles peut être utile je n'ai pas eu de scrupules à  te renvoyer à  la référence ;/

    dans 1284886932:

    PS : tu vois que tu as pris goût à  [Edit] !

    Oui, j'ai vraiment apprécié J J Rousseau le jour où j'ai lu sa description de l'esprit d'escalier, je m'y suis tant reconnu ..
  • MickMick Membre
    13:49 modifié #11
    Bonjour à  tous,

    J'ai finalement réussi à  créer une NSAttributedString géante. J'ai créé une NSTextView et lui ai refilé la string.
    Un printOperation me donne le résultat escompté... sauf que le découpage n'est pas correct pour les pages..

    Quel est l'usage pour gérer le problème des "sauts de pages" ? Je ne sais pas où chercher.
    Est-il correct d'utiliser une textView comme vue pour l'impression ? faut-il créer une vue perso ?

    pas facile les problèmes d'impression....
  • laudemalaudema Membre
    13:49 modifié #12
    dans 1285001469:


    Quel est l'usage pour gérer le problème des "sauts de pages" ? Je ne sais pas où chercher.
    Est-il correct d'utiliser une textView comme vue pour l'impression ? faut-il créer une vue perso ?

    pas facile les problèmes d'impression....

    Tu dois gérer toi même le découpage. Si ta vue est trop grande tu devras chercher le nombre de lignes maximales imprimables dans une page et dessiner autant de fois que nécessaire ta vue. Tout ça est assez bien expliqué dans le "Programmation Cocoa sous Mac OS X" de Hillegass (Chapitre 27, page 338 Gérer la pagination). Sinon tu as aussi la documentation Apple http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Printing/Concepts/pagination.html#//apple_ref/doc/uid/20001051-BBCHHAHI si tu veux "rapetisser" ta vue ou la "clipper" pour la laisser sur une page. http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Printing/Tasks/PaginatingViews.html#//apple_ref/doc/uid/20000912-BBCHHAHI si tu veux imprimer plusieurs pages.
  • MickMick Membre
    13:49 modifié #13
    Bonjour,

    Finalement j'ai fait une subclass de NSTextView. Je lui passe l'immense attributedString.
    J'override les méthodes suivantes :
    <br />- (BOOL)knowsPageRange:(NSRangePointer)range {<br />	range-&gt;location=1;<br />	//Il faut calculer ici le nombre de page !!!<br />	NSPrintInfo *pi=[[NSPrintOperation currentOperation] printInfo];<br />	NSSize paperSize=[pi paperSize];<br />	float hauteurPageAvantScale=paperSize.height-[pi topMargin]-[pi bottomMargin];<br />	float scale=[[[pi dictionary] objectForKey:NSPrintScalingFactor] floatValue];<br />	float hauteurPage=hauteurPageAvantScale/scale;<br />	int nbreTableauxParPage=hauteurPage/hauteurDUnTableau;<br />	range-&gt;length= nbreDeTableaux / nbreTableauxParPage + 1;<br />	return YES;<br />}<br /><br />- (NSRect)rectForPage:(int)page {<br />	NSPrintInfo *pi=[[NSPrintOperation currentOperation] printInfo];<br />	NSSize paperSize=[pi paperSize];<br />	float hauteurPageAvantScale=paperSize.height-[pi topMargin]-[pi bottomMargin];<br />	float scale=[[[pi dictionary] objectForKey:NSPrintScalingFactor] floatValue];<br />	float hauteurPage=hauteurPageAvantScale/scale;<br />	int nbreTableauxParPage=hauteurPage/hauteurDUnTableau;<br />	NSRect leRectADrawer=NSMakeRect(0.0,hauteurDUnTableau*(page-1)*nbreTableauxParPage,<br />							NSWidth([self bounds]),nbreTableauxParPage*hauteurDUnTableau);<br />	return leRectADrawer;<br />}<br /><br />
    

    Et ..... Le découpage des pages ne marche pas. En plus, il me met une erreur du type

    Gestion De Classe has exited with status 0.
    [Session started at 2010-09-23 11:48:03 +0200.]
    No object with name:
    PDE


    M'y prends-je comme un pied ? Au débug, ma hauteur de tableau semble correcte, le nombre de tableaux par page est correct, le nombre de page est correct.... les rectangles envoyés semblent aussi correct (la hauteur est bien nbreTableauParPage*hauteurDUnTableau). Et pourtant, l'aperçu me montre quelque chose qui n'a rien à  voir ! On dirait qu'une autre méthode rectForPage est appelée après la mienne !
  • laudemalaudema Membre
    13:49 modifié #14
    Bonjour Mick,

    ça semble bizarre que ta textView n'imprime pas correctement ton tableau. Si je crée un tableau dans TextEdit et que le fais s'imprimer les sauts de page sont gérés correctement, je ne vois pas pourquoi il en irait autrement.
    Essaye plutôt de définir pageRect en variable d'instance et de lui attribuer sa valeur dans le knowsPageRange. Je ne sais pas si ça changera quelque chose mais je l'ai toujours vu faire (et fait) comme ça. Pourquoi voudrais tu le faire varier, normalement il est toujours le même d'une page à  l'autre ?
  • MickMick Membre
    13:49 modifié #15
    Bonjour,

    ta dernière phrase me laisse penser que je n'ai pas compris le rectForPage

    Pourquoi voudrais tu le faire varier, normalement il est toujours le même d'une page à  l'autre ?


    J'ai compris que le rect retourné par rectForPage était le rectangle de ma view qui est sensé s'imprimer sur la page.
    Si tu me dit que ce rectangle est sensé ne pas changer pour chaque page, c'est que je n'ai pas compris ce qu'est le rect à  retourner...
  • laudemalaudema Membre
    septembre 2010 modifié #16
    Renseignements pris rectForPage peut varier

    Mais ce n'est pas le plus important car dans ton cas il ne variera que pour la dernière page.
    Par contre, si tu essayes de mettre un point d'arrêt dessus, via le menu Run ->Show Breakpoints (commande-option B), double click tout en bas pour ajouter un point d'arrêt -> rectForPage: avec les deux points, une sheet d'alerte se déplie et demande auquel particulièrement tu veux l'associer: celui qui est défini dans ton projet ou à  -[NSTextView(NSPrivate) rectForPage] ou à  [NSView(NSPrintig1) rectForPage] ce qui fait beaucoup de rectForPage susceptibles de se déclencher. Tu peux mettre des points d'arrêt avec un log ou un son différent pour chacun et voir lequel est appelé qui pourrait parasiter (probablement celui de la NSTextView).
    Il se pourrait fort que tu te battes avec les automatismes de la NSTextView.
    Peut être en changeant les paramètres d'impressions (du genre fitToPage) obtiendrais tu un résultat correct.
    Ou alors tu te passe d'elle pour imprimer, tu la gardes juste pour son layoutManager - textContainer - textStorage et tu imprimes tes tableaux les uns après les autres en regardant s'il te reste de la place.
    Voir ici
  • laudemalaudema Membre
    septembre 2010 modifié #17
    Pas assez de temps pour te répondre et essayer de mon côté Surtout sans avoir bien saisi si tu voulais imprimer un seul long tableau ou plusieurs. En plus mon dernier message a disparu, je n'ai pas dû appuyer sur le bon bouton :(

    Il me semble que tu te bats contre les automatismes de la NSTextView, peut être devrais tu essayer différents paramètres d'impressions (du genre fitToPage) et laisser faire les automatismes.

    Sinon il te faut repartir de ta NSAttributedString et utiliser les méthodes du NSLayoutManager pour la dessiner bout par bout, table par table si ce sont plusieurs tables. Mais le faire dans une sous classe de NSView plutôt que NSTextView. lien
    Tu as quelques démos dans XCode, tapes LayoutManagerDemo dans le champ de recherche de la documentation et aussi TextViewConfig pour avoir des exemples de codes qui utilisent ces concepts, mais pas dans l'impression mais l'impression n'est qu'une option dans le dessin des vues..

  • MickMick Membre
    13:49 modifié #18
    OK, merci Laudéma.
    Je pense effectivement que je dois me battre avec NSTextView.

    Sinon, pour le principe, je veux imprimer un certain nombre de tableaux, et je veux les arranger pour en mettre le maximum sur une même page. Le problème est de déterminer le nombre de tableaux par page, ce que je fais en calculant floorf(hauteurPage/hauteurDUnTableau).

    Après, c'est la conception de ces tableaux que je ne savais pas faire avant tes réponses (je ne connaissais pas les textTable). Donc j'ai opté pour la solution de créer une méga attributedString via une textTable (je sépare 2 tableau par une row vierge, je peux ajouter un titre à  mon tableau en ajoutant une row sans bordures..). Là  où je merdouille, par manque de connaissance de la gestion des textes, et malgré la lecture de la doc (je suis un peu paumé dans les différents objets), c'est d'afficher cette attributeString dans une vue. J'ai donc utilisé une textView. Le problème est qu'à  l'impression il ne faut pas qu'un des tableaux (contenu dans le tableau géant) soit coupé lors d'un saut de page. j'ai donc overridé la méthode rectForPage et je lui fait retourner le rectangle de la textView perso qui contient juste pile poil les bons tableaux à  imprimer sur la page.

    Je pense qu'il faudrait que je me passe de la textView, mais je ne sais pas trop gérer les layoutManager et tout ce qui s'en suit. Je vais essayer de me plonger à  fond dedans.
  • MickMick Membre
    13:49 modifié #19
    Bon, en fait je me suis aperçu que le problème vient du calcul EXACT du rectangle à  retourner à  la fin de rectForPage: En effet, je calcule la taille de l'attributedString géante par un [laString boundingRectWithSize:NSZeroSize options:NSStringDrawingUsesLineFragmentOrigin]. En divisant le height par le nombre de tableaux, je devrais tomber pile sur la hauteur d'un tableau et donc je devrais pouvoir n'afficher que le rectangle adéquat qui commence PILE sur le début d'un tableau et dont la taille fait PILE un tableau... Et c'est bien le mot PILE qui pose problème...

    Une idée ?
  • AliGatorAliGator Membre, Modérateur
    13:49 modifié #20
    Heu... FACE ?
  • MickMick Membre
    13:49 modifié #21
    Bien vu. C'est pas bien de se moquer  >:)
  • laudemalaudema Membre
    13:49 modifié #22
    dans 1285260974:

    Je pense qu'il faudrait que je me passe de la textView, mais je ne sais pas trop gérer les layoutManager et tout ce qui s'en suit. Je vais essayer de me plonger à  fond dedans.

    C'est un peu effrayant à  cause du nombre d'objets qui rentrent en jeu mais une fois qu'on est plongé dedans comme tu dis ça prend forme (c'est le cas de le dire ;-)

    De toutes façons, que tu gardes ou pas ta NSTextView tu devrais te plonger dedans et si tu utilises une NSTextView les composants sont là  déjà , selon la manière dont tu l'as créée

    If you use the NSTextView class to display text, either by dragging a text view object from the Interface Builder Data palette or creating a text view programmatically using the NSTextView method initWithFrame: method, Cocoa automatically creates an NSLayoutManager instance to draw your text. If you create a text view using the NSTextView initWithFrame:textContainer: method, however, or if you need to draw text directly into a different type of NSView object, you must create the NSLayoutManager explicitly.
    http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextLayout/Tasks/DrawingStrings.html%23//apple_ref/doc/uid/20001808-DontLinkElementID_11

    NSTextStorage est en fait une (sous classe de) NSAttributedString c'est lui qui retient le(s) layoutManager(s) et le(s) textContainer(s)
    http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/TextArchitecture/Tasks/AssembleSysByHand.html%23//apple_ref/doc/uid/20000843-CJBBIAAF

    Dans ton cas il faudrait voir combien la NSAttributedString possède de containers en le demandant au layoutManager, peut être en met elle autant que de tableaux ? Il se peut aussi qu'elle rajoute un espace entre chaque tableau, au moins un retour à  la ligne, faussant par là  tes calculs.
    Faute de temps je ne suis pas capable de vérifier mais il me semble qu'un bout de code intéressant existe dans la documentation avec la demo de TextEdit pour la méthode setHasMultiplePages
    <br />/* This method sets whether the document has multiple pages or not. It can be called at anytime. force indicates whether to do the task even if the values are the same (usually needed for the first call).<br />*/&nbsp;  <br />- (void)setHasMultiplePages:(BOOL)flag force:(BOOL)force {<br />&nbsp; &nbsp; NSZone *zone = [self zone];<br /> <br />&nbsp; &nbsp; if (!force &amp;&amp; (hasMultiplePages == flag)) return;<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; hasMultiplePages = flag;<br /> <br />&nbsp; &nbsp; if (hasMultiplePages) {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSTextView *textView = [self firstTextView];<br />&nbsp; &nbsp; &nbsp; &nbsp; MultiplePageView *pagesView = [[MultiplePageView allocWithZone:zone] init];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; [scrollView setDocumentView:pagesView];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; [pagesView setPrintInfo:[self printInfo]];<br />&nbsp; &nbsp; &nbsp; &nbsp; // Add the first new page before we remove the old container so we can avoid losing all the shared text view state.<br />&nbsp; &nbsp; &nbsp; &nbsp; [self addPage];<br />&nbsp; &nbsp; &nbsp; &nbsp; if (textView) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [[self layoutManager] removeTextContainerAtIndex:0];<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; [scrollView setHasHorizontalScroller:YES];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; // Make sure the selected text is shown<br />&nbsp; &nbsp; &nbsp; &nbsp; [[self firstTextView] scrollRangeToVisible:[[self firstTextView] selectedRange]];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; NSRect visRect = [pagesView visibleRect];<br />&nbsp; &nbsp; NSRect pageRect = [pagesView pageRectForPageNumber:0];<br />&nbsp; &nbsp; &nbsp; &nbsp; if (visRect.size.width &lt; pageRect.size.width) { // If we can&#39;t show the whole page, tweak a little further<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSRect docRect = [pagesView documentRectForPageNumber:0];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (visRect.size.width &gt;= docRect.size.width) { // Center document area in window<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; visRect.origin.x = docRect.origin.x - floor((visRect.size.width - docRect.size.width) / 2);<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (visRect.origin.x &lt; pageRect.origin.x) visRect.origin.x = pageRect.origin.x;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; // If we can&#39;t show the document area, then show left edge of document area (w/out margins)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; visRect.origin.x = docRect.origin.x;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [pagesView scrollRectToVisible:visRect];<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; } else {<br />&nbsp; &nbsp; &nbsp; &nbsp; NSSize size = [scrollView contentSize];<br />&nbsp; &nbsp; &nbsp; &nbsp; NSTextContainer *textContainer = [[NSTextContainer allocWithZone:zone] initWithContainerSize:NSMakeSize(size.width, FLT_MAX)];<br />&nbsp; &nbsp; &nbsp; &nbsp; NSTextView *textView = [[NSTextView allocWithZone:zone] initWithFrame:NSMakeRect(0.0, 0.0, size.width, size.height) textContainer:textContainer];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; // Insert the single container as the first container in the layout manager before removing the existing pages in order to preserve the shared view state.<br />&nbsp; &nbsp; &nbsp; &nbsp; [[self layoutManager] insertTextContainer:textContainer atIndex:0];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; if ([[scrollView documentView] isKindOfClass:[MultiplePageView class]]) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NSArray *textContainers = [[self layoutManager] textContainers];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; unsigned cnt = [textContainers count];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (cnt-- &gt; 1) {<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [[self layoutManager] removeTextContainerAtIndex:cnt];<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />&nbsp; &nbsp; &nbsp; &nbsp; }<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; [textContainer setWidthTracksTextView:YES];<br />&nbsp; &nbsp; &nbsp; &nbsp; [textContainer setHeightTracksTextView:NO];&nbsp; &nbsp;  /* Not really necessary */<br />&nbsp; &nbsp; &nbsp; &nbsp; [textView setHorizontallyResizable:NO];&nbsp; &nbsp; &nbsp; &nbsp;  /* Not really necessary */<br />&nbsp; &nbsp; &nbsp; &nbsp; [textView setVerticallyResizable:YES];<br />&nbsp; &nbsp; [textView setAutoresizingMask:NSViewWidthSizable];<br />&nbsp; &nbsp; &nbsp; &nbsp; [textView setMinSize:size]; /* Not really necessary; will be adjusted by the autoresizing... */<br />&nbsp; &nbsp; &nbsp; &nbsp; [textView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; /* Will be adjusted by the autoresizing... */&nbsp; <br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; /* The next line should cause the multiple page view and everything else to go away */<br />&nbsp; &nbsp; &nbsp; &nbsp; [scrollView setDocumentView:textView];<br />&nbsp; &nbsp; &nbsp; &nbsp; [scrollView setHasHorizontalScroller:NO];<br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; [textView release];<br />&nbsp; &nbsp; &nbsp; &nbsp; [textContainer release];<br /> <br />&nbsp; &nbsp; &nbsp; &nbsp; // Show the selected region<br />&nbsp; &nbsp; &nbsp; &nbsp; [[self firstTextView] scrollRangeToVisible:[[self firstTextView] selectedRange]];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; [[scrollView window] makeFirstResponder:[self firstTextView]];<br />&nbsp; &nbsp; [[scrollView window] setInitialFirstResponder:[self firstTextView]];&nbsp; &nbsp; // So focus won&#39;t be stolen (2934918)<br />}<br />
    

    MultiplePageView est une classe qui semble aussi très prometteuse
    <br />@interface MultiplePageView : NSView {<br />&nbsp; &nbsp; NSPrintInfo *printInfo;<br />&nbsp; &nbsp; NSColor *lineColor;<br />&nbsp; &nbsp; NSColor *marginColor;<br />&nbsp; &nbsp; unsigned numPages;<br />}<br /> <br />- (void)setPrintInfo:(NSPrintInfo *)anObject;<br />- (NSPrintInfo *)printInfo;<br />- (float)pageSeparatorHeight;<br />- (NSSize)documentSizeInPage;&nbsp;  /* Returns the area where the document can draw */<br />- (NSRect)documentRectForPageNumber:(unsigned)pageNumber;&nbsp;  /* First page is page 0 */<br />- (NSRect)pageRectForPageNumber:(unsigned)pageNumber;&nbsp;  /* First page is page 0 */<br />- (void)setNumberOfPages:(unsigned)num;<br />- (unsigned)numberOfPages;<br />- (void)setLineColor:(NSColor *)color;<br />- (NSColor *)lineColor;<br />- (void)setMarginColor:(NSColor *)color;<br />- (NSColor *)marginColor;<br /> <br />@end<br />
    

    Je regrette vraiment de n'avoir pas de temps pour y regarder plus. Mais arrivé là  je pense que tu ne dois plus être loin du but et que désormais les impressions Cocoa n'auront plus de secrets pour toi ;)
  • MickMick Membre
    13:49 modifié #23
    Bon, au bout du compte, j'ai réalisé qu'il était beaucoup plus fiable de créer une NSView perso avec une variable d'instance int qui contient la page courante pour l'impression (donc à  mettre à  jour dans l'appel de la méthode rectForPage).
    Du coup, cette vue n'affiche que ce qui est sur la page donnée. Ainsi, plus de problème de découpage "pile" d'une vue géante qu'on découperait en petits morceaux (un pour chaque page). Je me suis inspiré de l'exemple simple de notre cher Aaron..
Connectez-vous ou Inscrivez-vous pour répondre.