プリント機能を加える

ここでは、アプリケーションでプリント機能をいじる方法をメモする。ほんとにさわりだけ。

普通に Window-based アプリケーションを作ると、標準では Print... を実行するとウィンドウ自体が印刷される。

NSTextView があると、一つだけなら、その Text View が印刷される。Document-based アプリケーションでも、

試してないけどたぶん同じで、NSTextView があるウィンドウがあれば Text View の内容がプリントされる。

標準でプリントするのになんでメモを?というのは、Document-based アプリケーションを作っているときに、

RTF にしてルーラーを表示させて、Text View を制限してプリントするときの用紙サイズにあわせたプリントエリアと、

それに伴うマージンを設定しようと思ったときに、そのままにすると、NSTextView を制御している Text Container が

Line Fragment Padding というのを勝手に入れてて、画面上でちゃんと調整しても、プリントすると余分な余白が入るので、

左側に入った分だけ右側が削られる。5ポイントだからほんのわずかだけど、文字が切れるのは使い勝手が悪い。

かといって、Line Fragment Padding をなくすと、Text View 上で左端がぎりぎりまでくるので見にくい。

ちなみに、Line Fragment Padding をなくすには、まず、textContainer という NSTextView のメソッドで

Padding を変更したい Text View の Text Container にアクセスして setLineFragmentPadding(float) で変更する。

float なので、point で小数で指定する(たぶん整数でも大丈夫と思う)。

@textView.textContainer.setLineFragmentPadding(0.0)

さて、標準のプリント機能じゃなくするには、プリント処理をするメソッドを作り ib_action としてプリント...

メニューアイテムに結びつける。ここでは printDoc という名前にしておく。

def printDoc(sender)

ここに処理を入れる。

end

プリントをするときの余白などの情報は、NSPrintInfo で管理している。どのアプリケーションでもアクセスできるように

コンピューターで管理している共通の設定があるんだけど、それをまず読み込んで、必要なところだけ変えて使いたい。

それには、sharedPrintInfo というメソッドを使ってアクセスする。これでは使えないので、dictionary というメソッドで

dictionary オブジェクトにする(NSPrintInfoDictionaryProxy というオブジェクトが返ってきた)。

defaultPrintInfo = NSPrintInfo.sharedPrintInfo.dictionary

この中に何が入っているかを見ると、次のようなものがあった。どんなフォーマットで入れるかは自分で探ってください。

NSPrinter

NSPrinterName

NSFirstPage

NSLastPage

NSLeftMargin

NSRightMargin

NSTopMargin

NSBottomMargin

NSSavePath

NSMustCollate

NSPagesDown

NSHorizonalPagination

NSDetailedErrorReporting

NSPrintTime

NSPrintProtected

NSVerticalPagination

NSHorizontallyCentered

NSFaxNumber

NSOrientation

NSJobDisposition

NSPrintSpoolJob

NSPrintAllPages

NSCopies

NSPaperName

NSPaperSize

NSScalingFactor

NSVerticallyCentered

NSPagesAcross

この dictionary オブジェクトを使って、initWithDictionary で新しい NSPrint オブジェクトを作る。

printInfo = NSPrintInfo.alloc.initWithDictionary(defaultPrintInfo)

で、今回は左右の余白を変えたいので、setLeftMarginsetRightMargin というメソッドを使う。

上で書いたように NSTextView には、左右に 5 point ずつの余白が入れられているので、その分だけ余白を削る。

defaultPringInfo["NSLeftMargin"]、defaultPringInfo["NSRightMargin"] で左右の余白を取り出して、to_f で

Ruby の float にして、そこから5を引いている。

printInfo.setLeftMargin(defaultPringInfo["NSLeftMargin"].to_f - 5)

printInfo.setRightMargin(defaultPringInfo["NSRightMargin"].to_f - 5)

あと、デフォルトでは、余白を除いたページの中心に View のイメージが印刷されるので、ちゃんと紙の大きさや

余白の設定がされていれば、かえって困ることになる。例えば、ページが満たされてなかったとすると、

前のページの続きではなく、最後の残りはページの中央に配置されることになる。これを避けるために、

setHorizontallyCentered(true/false)setVerticallyCentered(true/false) で両方ともこの設定を切る。

printInfo.setHorizontallyCentered(false)

printInfo.setVerticallyCentered(false)

これ以外のものも変更できるけど、試してないのでここには書かない。それ以外にも、情報を取って

プリントする文書に付け加えたりできるんじゃないかと思う。

プリントする情報が整ったら、プリントを実行する。それには NSPrintOperation を使う。まず、printOperationWithView_printInfo

プリントする View と PrintInfo から、NSPrintOperation オブジェクトを作る。ここでは、@textView という Text View と、

今作った printInfo という NSPrintInfo オブジェクトを使う。

printOp = NSPrintOperation.printOperationWithView_printInfo(@textView,printInfo)

これを使って実行するには runOperationrunOperationModalForWindow_delegate_didRunSelector_contextInfo(window,delegate,selector,info)

というメソッドを使う。Save Panel Open Panel と同じく、前者が単独のウィンドウで後者が印刷する View が乗っているウィンドウからでてくるパネルになる。

window は印刷する View の乗ってるウィンドウ、delegate は印刷パネルが開いたときに情報が送られる先なので、今スクリプトを書いているクラスに

なるように self を入れる。selector は情報が返ってくる delegate メソッドで、printPanelDidEnd_success_contextInfo(printOperation,success,info) なんてのが

デベロッパドキュメントの例にあったので、そうしてみる。実際は、3つの情報が受けられるようなメソッドを書けばいいと思う。

ちなみに、Document-based アプリケーションで NSDocument のサブクラスのファイルでこれをするときは、window には self.windowForSheet を入れる。

printOp.runOperationModalForWindow_delegate_didRunSelector_contextInfo(@window,self,:printPanelDidEnd_success_contextInfo,nil)

これで、成功すれば success に true (Yes) が返ってくる。まあ、ただ return としておけば普通に動くようだ。

def printPanelDidEnd_success_contextInfo(printOp,success,info)

return

end

これで、目的は達せられた。最後に、ここまでのをまとめてみた。

def printDoc(sender)

defaultPrintInfo = NSPrintInfo.sharedPrintInfo.dictionary

printInfo = NSPrintInfo.alloc.initWithDictionary(defaultPrintInfo)

printInfo.setLeftMargin(defaultPringInfo["NSLeftMargin"].to_f - 5)

printInfo.setRightMargin(defaultPringInfo["NSRightMargin"].to_f - 5)

printInfo.setHorizontallyCentered(false)

printInfo.setVerticallyCentered(false)


printOp = NSPrintOperation.printOperationWithView_printInfo(@textView,printInfo)

printOp.runOperationModalForWindow_delegate_didRunSelector_contextInfo(@window,self,:printPanelDidEnd_success_contextInfo,nil)

end

ib_action :printDoc

def printPanelDidEnd_success_contextInfo(printOp,success,info)

return

end