「Mac」カテゴリーアーカイブ

iPod Touch ってマウントしないのかぁ

iPalmMemo のメモを iPod Touch のメモ帳へ転送、と言うか同期したかったのですが。なんと今までの iPod と違ってマックに接続しても iTunes に表示されるだけで HD としてマウントする設定が有りませんでした。これじゃぁ iPod の時の様にコピー出来ないじゃぁ無いですか。で、iTunes で同期する項目を見てみると、なんとアドレス帳や予定は有るのにメモ帳が無い。またしても拒否されてしまった。
しかたないので同期に関しては Apple のバージョンアップを待つことにしました。Apple の同期は Sync Services を使います。iPod は Palm、携帯電話 等と同じく iSync で同期します。しかし iPod Touch は異なるようです。ちょっと調べてみると AppleMobileSync.app と AppleMobileDeviceHelper.app で行っている様です。Helper の方は常に起動していて接続を検出しているのでは無いでしょうか?
AppleMobileSync.app が同期する種類、項目には iTunes で設定出来る種類、項目が指定されていましたが、やはりメモに関しては記述が有りませんでした。 AppleMobileSync.app 内の定義ファイルを調べれば分かるはずです。私は Developer をインストールすると使用できる Syncrospector.app を使って調べました。これは、どのプログラムがどんな項目を同期しているのか、いつ同期したのか、等いろいろと見ることが出来るアプリケーションです。

iPlamMemo の事に戻って、Mail.app のメモ帳とも同期したかった事も有り、Sync Services を使ったテストプログラムを作成して色々とテストしています。もし iPod Touch のメモ帳が Mail.app のメモ帳と同期できる様になったら iPlamMemo のメモとも同期出来るので、いいかも。でも Mail.app のメモ帳って HTML なんですよねぇ。iPalmMemo と同期する時の問題としては HTML 以外にカテゴリの問題が有ります。なので、現状では特定のカテゴリを同期する方向で考えています。

QueueMemo は Leopard で変な動きをする様になったから対応しないといけないし、もう少し使いやすい様にしたいし、iPalmMemo のコンジットでバグが有って先日やっと修正したし、MissingSync のコンジットの方が開発しやすいので全部移行したいけど無理だし、モーションエディタも画面からぐりぐり出来る奴を開発したいし、、、
まぁ最近はちょっとモチベーションも上がって来たので少しずつリリース出来るのでは、と考えています。
(最初 iPod Touch で日本語の入力方法を知らなくて入力出来なかったのは内緒)

Xcode 3.0

Mac OS が Leopard になって Xcode もバージョンアップされたのですが、ご存じの様に暫くプログラミングして無かった為、最近になってやっと見ました。IB がかなり変更されていてびっくりしました。やることは同じなのですが方法が変更になって、また一からあちこち参照しなくても作成出来る様になるまで色々やらなければ。
私にとっては新しい技術で有る CoCoa Binding やら Core Data 等もこれを機会に習得したいと思ってます。

MotionPlayer をリリースしました

マックで RCB-3HV のモーション・シナリオを再生する MotionPlayer をリリースしました。これは以前書いていた RCBCommander の名前を変更した物です。近藤科学さんからリリースされているプログラムと同じ名前もどうかと。だいたい機能が違うし。で、変更しました。
添付ドキュメントにも書いていますが、現状では USB アダプタで使用しているチップのウェブサイトからライブラリをダウンロードしてインストールする必要が有ります。普通にファイルをコピーするだけなら良いのですが unix のコマンドを使う必要が有るので、詳しくない人には難しいかも。
将来的にはドライバを作成してインストーラ形式が良いと思ってはいるのですが、ドライバがねぇ。

Mac OS X での印刷処理

これはドキュメントタイプでは無いアプリケーションで印刷を行おうと戦った結果です。間違っている所は多々あると思いますが、参考になれば幸いです。
まず、Mac OS X での印刷は印刷するビューを作成してそれを NSPrintOperation で指定すれば可能です。言い換えれば印刷するビューを作成しないと印刷出来ない、と言う事になります。
プログラムでは NSView のサブクラスを作成します。「Print」アクションを受け取るとまず現在設定されている用紙の情報を取得します。
NSPrintInfo *pinfo = [NSPrintInfo sharedPrintInfo];
NSSize paperSize = [pinfo paperSize];
で、印刷するビューを作成します。
PrintView *view;
vew = [[PrintView allocWithZone:[self zone]]
initWithFrame:NSMakeRect(
0.0, 0.0, paperSize.width, paperSize.height)
memos:item];
私はメモを印刷するのでここでメモの情報をセットしています。別に後でも良いかも。
印刷するフォントを設定します。
[view setFont:mTextFont];
印刷する対象が既にフォーマットに関する情報を持っているのなら不要だと思います。私の場合素のテキストなので既定のフォントをセットしています。
NSPrintOperation *op = [NSPrintOperation
printOperationWithView:view
printInfo:pinfo];
[op setShowPanels:YES];
[op runOperation];
これで印刷パネルが表示されます。
その後ビューをリリースします。
[view release];
これで本体側の処理は終わりです。

次に印刷されるビューに関して。
最初は生成時に呼ばれる initWithFrame です。
– (id)initWithFrame:(NSRect)frame memos:(ListItem*)ListItem;
ここでは、まず NSView のフレームのセットと印刷する内容を保持する NSTextStorage レイアウトを担当する NSLayoutManager 実際の表示を担当する NSTextContainer をそれぞれ初期化します。
self = [super initWithFrame:frame];
まず NSView のフレームをセットします。 NSView のサブクラスなので親に対してセットします。
次にNSTextStorage を生成します。
mTextStorage = [[NSTextStorage alloc] init];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSLayoutManager を生成します。
[layoutManager setDelegate:self];
NSLayoutManager のデリゲートに自分をセットします。
NSTextContainer *textContainer = [[NSTextContainer alloc] init];
NSTextContainer を生成します。
NSSize tcSize;
tcSize.width = frame.size.width;
tcSize.height = frame.size.height;
NSTextContainer は最初どんな大きさでも表示出来るように可能な最大の大きさを持っていますので、ここでは印刷する1ページの大きさをセットします。
[textContainer setContainerSize:tcSize];
[layoutManager addTextContainer:textContainer];
[textContainer release];
NSTextContainer を NSLayoutManager にセットしリリースします。
[mTextStorage addLayoutManager:layoutManager];
[layoutManager release];
NSLayoutManager を NSTextStorage にセットしてリリースします。
[mTextStorage retain];
NSTextStorage は retain します。drawRect とかで使用するので。

ここで NSTextStorage に印刷するメモの内容をセットしても良いのですが(最初はここでセットしていた)私の場合フォントをセットするので、そのメソッドで行いました。
でもメモのオブジェクトが有るので、それをクラス変数にセットして retain しています。

NSTextStorage に印刷する内容をセットするのですが、NSTextStorage を変更する場合は処理の前に
[mTextStorage beginEditing];
変更が終わった後で
[mTextStorage endEditing];
を実行する必要が有ります。
さらに NSTextStorage にセットする内容は NSAttributedString となります。
特に編集する必要が無い場合は
NSAttributedString *memoAttr = [[NSAttributedString alloc] initWithString:memo];
で大丈夫です。色々とフォントや大きさ、色、等を変更したい場合はここで行って下さい。
[mTextStorage appendAttributedString: memoAttr];
で印刷したい文字列を NSTextStorage にセットします。
ここで印刷したい内容が1ページに収まる場合は特に問題も無く、何もしなくても印刷出来ます。
1ページに収まらない場合は NSLayoutManager に Delegate をセットしたので
– (void)layoutManager:(NSLayoutManager *)aLayoutManager didCompleteLayoutForTextContainer:(NSTextContainer *)aTextContainer atEnd:(BOOL)flag
が呼び出されます。
ここで aTextContainer が nil の場合 NSTextStorage の内容を NSLayoutManager が NSTextContainer に配置していったが一杯になった、と言う事なので initWithFrame でやった様に
NSTextContainer を生成して NSLayoutManager に追加してやります。
NSTextContainer *textContainer = [[NSTextContainer alloc] init];
NSSize tcSize;
tcSize.width = paperSize.width;
tcSize.height = paperSize.height;
[textContainer setContainerSize:tcSize];
[aLayoutManager addTextContainer:textContainer];
[textContainer release];
そして印刷する範囲が広がったのでこの印刷ビューの大きさも大きくします。
NSRect frame = [self frame];
frame.size.height += paperSize.height;
[self setFrame:frame];
で、これが不思議なのですが追加した NSTextContainer のグリフの範囲を取得すると旨く動作します。
NSRange glyphRange = [aLayoutManager glyphRangeForTextContainer:textContainer];
これを実行しないと再度 NSTextContainer が一杯になった時このデリゲートが呼ばれません。
呼ばれないと印刷できない情報が残ってしまいます。
NSLayoutManager のデリゲートにはもう一つ
– (void)layoutManagerDidInvalidateLayout:(NSLayoutManager *)aLayoutManager
が有ります。レイアウトが無効になった時呼び出される、とか。
私は理解出来てませんが、この中では
int glyphNum = [aLayoutManager numberOfGlyphs];
と NSLayoutManager のグリフの数を取得すると旨く動作します。
複数ページ印刷する場合は NSLayoutManager のデリゲートが何度か呼び出されて NSTextContainer を NSLayoutManager に追加する、と言う処理を行います。

実際の1ページの印刷処理は
– (void)drawRect:(NSRect)rect
が担当します。
NSLayoutManager *layoutManager = [[mTextStorage layoutManagers] objectAtIndex:0];
で NSLayoutManager を取得します。今回は NSLayoutManager を1個しか使って無いので NSArray の最初のオブジェクトです。
次に NSTextContainer を取得しますが複数ページの場合 NSTextContainer が複数存在するので印刷対象のページの NSTextContainer を取得します。
NSTextContainer *textContainer = [[layoutManager textContainers] objectAtIndex:page];
取得した NSTextContainer で印刷可能なグリフ範囲を取得します。
NSRange glyphRange = [layoutManager
glyphRangeForTextContainer:textContainer];
で、取得したグリフ範囲を描画します。
[self lockFocus];
[layoutManager drawGlyphsForGlyphRange: glyphRange atPoint: rect.origin];
[self unlockFocus];

以上で、とりあえず印刷は可能です。
今後の課題としては
・デリゲートが追加した NSTextContainer のグリフ範囲を取得しないと続けて呼び出されないのは何故?
・今回は印刷ビューの中でレイアウト処理を行ったが、良いのか?
・先にレイアウトを行って準備出来てから印刷ビューを作成した方が良いのか?

まぁ初めての印刷処理にしては上出来かな、えっ?参考にもならない、すみません。

ログイン時に起動するプログラムの登録・削除

システム環境設定でアカウントを選択「ログイン項目」タブを選択するとログイン時に起動されるプログラムの一覧が表示されます。ここに登録するとログイン時自動的に起動されます。ここの登録・削除(まぁ変更も出来ますが)をプログラムから行いたい人はサンプルが developer.apple.com に有るので参考にしてみて下さい。
http://developer.apple.com/samplecode/LoginItemsAE/
AppleEvent を c プログラムから発行して制御しています。