ラベル COCOA の投稿を表示しています。 すべての投稿を表示
ラベル COCOA の投稿を表示しています。 すべての投稿を表示

火曜日, 9月 24, 2013

備忘:どのquick pluginが動いているか調べる


なぜか、意図しないフォルダにある、quicklook プラグインが有効になってしまって
いることがある。

以下のコマンドで ファイルタイプ (UTI)に対して
どのフォルダに存在するpluginモジュールが有効となっているかわかる。

qlmanage -m plugins | grep ファイルタイプ




金曜日, 9月 20, 2013

備忘:イベントハンドラー以外の場所で modifierFlags を調べる


mouseDown などのイベントハンドラー以外の場面で、
commandキー optionキー等の状態を知りたい場合

[NSEvent modifierFlags] で調べられます。

例えばドラッグの最中に optionキーの状態を捉えたい場合

- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender;

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender;

の中では

([NSEvent modifierFlags] & NSAlternateKeyMask) 


によって、状態を把握できます。

以上


月曜日, 4月 23, 2012

Quick Look Pluginの補足

Quick look プロジェクトの設定にはいつもはまる
たまにしかやらないことなのでいろいろ忘れがちだ。
これは自分のためのメモ。

XCode4.3でテストする際、
スキーマの編集から実行プログラム qlmanage を指定しておく必要がある。
しかし、/usr/bin ディレクトリが、見えないので
プログラムファイルをブラウズして選ぶことができない。
直接入力することもできない。困ったものだ。

まず、なんでもいいから関係のないアプリを選んでおく。
その後XCodeを閉じて、プロジェクトファイル(xcodeproj)パッケージ
の中を掘り下げていき、そのQLターゲットのスキーマファイル(xcscheme)を見みつける。これはプロパティリストである。
この中に、先ほど適当に指定しておいたアプリの箇所がある。
これを /usr/bin/qlmanage に置き換える。

以上

金曜日, 12月 09, 2011

CHIRASHI App

CHIRASHI というMacアプリを作りました。
3日ほど前にMac App Storeのレビューがおわり、公開されました。
http://itunes.apple.com/jp/app/chirashi/id482532068?mt=12

1年ほど前からMacでアプリを開発をしようと思い立って、
この夏、8月末頃にCHIRASHIの開発に着手しました。
結局3ヶ月ほどかかりました。
最初はなめていて、頭の中では一ヶ月くらいで作れるつもりだった。
最初の一ヶ月でXCodeのプロジェクトから4度やり直し、おおむね現在の
見た目になった。10月の2週間くらいでQRコードとJANコードの生成ロジック
を実装し、概ね今の外観になった。
しかし、嫁さんに見せたところ、かなりいまいちな評価となった。
文字が入力しづらいとか、文字の表示がピンぼけになっているとか、図形が足りないとかいろいろ。。。
そこで再度見直した。レイヤーで文字を描画するとピンぼけることがわかり、レイヤーの使用をやめたり、描画コードを書き直し、入力方法も見直した。図形を大幅に追加することを決め、別途図形描画ツールを作ったりした。
Mac App Storeの基準をよくよく調べると、OS X Lionでの動作が必須となっていた。結局、OSをLionに更新した。XCodeのバージョンも上がった。Lionの新機能 フルスクリーンモード、オートセーブ、バージョンなんかについては最初、懐疑的だったが、使ってみると、すばらしいと感じた。そこで、対応することにした。対応すると、他にも気に入らないところがでてくる。だから磨いた。 ぷきぷき。。。

Appleの開発ガイドを読んでいると、開発のフェーズは、大まかに言うと

  • デザイン
  • 実装とテスト
  • 磨く (Polish)

からなる。
Polishが重要なのだという。Polishはテストではない。納得できるまで磨くのだ。
納得できなければリリースするべきではない。
と言うと、私のアプリは永遠にリリースできなさそうであるが、、、


11月下旬にやっとApp Storeにレビューを申請した。その数日後、不具合に気がつき、
申請を取り下げ、再申請をしたりしたあげく、無事レビュー完了の知らせが届いた。

AppStoreに公開されたのは嬉しかった。
また、次にむけてがんばろー。おー。

日曜日, 11月 06, 2011

Cocoaでの縦書きの実現について

OS/X 10.7 (Lion)では、NSTextView でも日本語のような
縦書による入力が可能になった。
OS標準のテキストエディタでも縦書きができるように
なっている。じぶんではあまり縦書きの文書は書かないので
あるが、使ってみると、なかなかいい。テキストカーソルは
水平になり、変換候補も横方向に縦書きで表示されるので
とても面白い。

NSTextView でレイアウトを縦書きにするには

setLayoutOrientation: で
NSTextLayoutOrientationVertical を指定するだけでよいことが
わかった。これだけで、テキストエディタと同じように縦書きで
テキスト入力ができる。

では、NSTextViewを使わずに、NSViewに縦書きのテキストを表示する
にはどうすればいいのか?
以前調べたときCoreTextを使って実現する方法がわかったが、
結構面倒なことになってしまったが、10.7になって、もっと楽な
方法ができたようだ。
CoreTextを使わずにCocoaのテキスト関連クラスで実現できる。
 NSTextStorage
 NSTextContainer
 NSLayoutManager

このうちNSTextStorage はNSMutableAttributedStringを継承している。
つまり、テキストの書式などの属性はテキストと共にNSTextStorageに格納する。
ここで、属性として NSVerticalGlyphFormAttributeName を設定すればよいようだ。

NSTextStorage *textStorage; があるとして、

    [textStorage addAttribute:NSVerticalGlyphFormAttributeName 
                      value:[NSNumber numberWithBool:YES] range:NSMakeRange(0, [textStorage length])];


のように指定する。
これで、日本語の文字はは左に90度回転した状態で水平方向に並ぶようになる。


あとは、あなたも首を90度傾ければ、縦書き表示が実現する。

首がつかれるので、いやだ? 

冗談はさておき、最初私は、さらに90配置を変更してくれる設定があるのだろうと
探していたが、見つからなかった。
じゃあ、Drawする前に、コンテキストに90度の回転を加えれば、それらしくなる
のかなと思ったのであった。ようは首を傾けるかわりにモニターを傾けるようなものだ。
その際に、表示域の縦と横を入れ替えてTextContainerに指定すればつじつまがあいそうだ。
でも、なんかしょぼい気がするし、NSTextViewはどうやっているのか気になった。
そこでヘッダファイルの説明を読むと、90度回転して表示しているらしいとわかった。
なんだ、同じじゃん!

コンテキストを回転するには     CGContextRotateCTM で90度時計回りの回転を
指定する。私のアプリはもともと任意の角度での回転を施していたんで、回転に
90度を足すだけだった。
やってみると、非常にいいあんばいになった。
もともと水平方向の描画をコンテキストで90回転しているだけなので、
水平方向のテキストアライメント(右寄せとかセンタリングとか)がそのまま
垂直方向に働く。よって縦書きテキストが上寄せ、中央寄せ、下寄せというように。

しかし細かいところで、課題が残った。
例えば水平テキストにアンダーラインを引くと当然、それは文字の下に線が引かれる
ことになるが、垂直なテキストでの傍線は私の実現方法では左側になってしまう。
それは普通、右側に引くものか?という点が気になる。
たぶんそうだ。右利きで鉛筆で縦書きに傍線を引くとき、左側に引こうとすれば
文字が隠れてしまう。よって、右側に引くのが自然だ。
でも、縦書きの印刷物で傍線が引かれたものなんて余り見かけないような気がする。


Appleの人も右側だと考えているようだ。テキストエディタでも右側に
傍線が引かれるようになっている。
しかし、これを実現する方法は今のところわからない。


土曜日, 11月 05, 2011

NSScrollView内のNSViewの位置について

OS/X では、NSViewなどのコンテンツを表示するビューを
NSScrollView内に配置すると、そのNSViewは左下隅に貼り付く。
原点を左上隅にあわせるためには、そのNSViewのサブクラスにて
BOOL isFlipped をオーバーライドして {return YES} を
返すようにすればよい。

であるが、ウィンドウをリサイズして、NSScrollViewが小さくなったときに
表示されている内容が上にスクロールしてしまう。

(NSScrollViewは自動的にリサイズするようにしておいたとして。)

絵にするとこんな感じである。
ウィンドウをリサイズすることにつれてスクロールビューもちいさくなる。
そのとき、狭くなった分だけ、表示されている内容が上に上がってしまう。



普通のアプリケーションはそのような状態にはなっていないので、当然なんとかなるはずが
その方法がわからず、なやんだ。
Appleのサンプルプログラムのsketchの状態を調べているうちに
やっと違いが見つかった。

Interface Builder のSize Inspector でのAutosizingの設定が不足していた
ことが原因だった。
これは、コンテンツのNSViewの設定である。

不十分な設定

対策
これによって、問題が解決した。
簡単なことであったが、知らないばかりに悩んでしまった。

まあ、いつも思うことだが、複雑な解決策は何か遠回りをしているものだ。
何かを解決できずはまってしまう時は、間違った方向に難しく考えすぎている
可能性がある。また、その方向で、何とか実現できたとしても、
その方法が自分でも気に入らない時は、おそらく、まだベストではない。
もっとシンプルな方法が見つかるはずなのだ。

木曜日, 10月 27, 2011

Quick Look Pluginプロジェクトの準備

自分のアプリケーションのドキュメントファイルにファインダーなど
でサムネイルやプレビューを表示するためには、
Quick Look Plugin を作成するという方法がある。

1) XCode 新規プロジェクトで System Plug-in  の Quick Look Plug-inを選択する。


2) アプリケーションのソースコードを(必要な奴だけ)プロジェクトに参照で追加する。

3) GenerateThumbnailForURL.c , GeneratePreviewForURL.c を
 の拡張子を.m に変更する。
    必要ならばincludeするライブラリを変更する。
 //#include <CoreFoundation/CoreFoundation.h>
 #include <Cocoa/Cocoa.h>

 アプリケーションソースもインクルードする
 例)
 #include "MyDocument.h"  

4) フレームワークの変更
  必要ならばCocoa.frameworkを追加する。

5) info.plist の編集
  Document types
    Document Content Type UTIs
      Item SUPPORTED_UTI_TYPE    
  
  SUPPORTED_UTI_TYPEを自分のアプリケーションのUTIに変更する

6) ターゲットにファイルをコピーするビルドフェーズを追加する。
   ※絶対パス
   ※コピー先: ~/Library/QuickLook   (/Library/QuickLook も可)

  そしてビルドフェーズに Product のオブジェクトを追加(ドラッグで)する。

7) GenerateThumbnailForURL.c , GeneratePreviewForURL.cを編集する。

8) テストツールを設定する。
 メニュー:プロジェクト→新規カスタム実行可能ファイル
   /usr/bin/qlmanage 
  引数を指定する。
   -p  documentFile.name       プレビューの場合
   -t   documentFile.name  サムネイルの場合

以上!

水曜日, 9月 14, 2011

Cocoaでの上下逆さま

Cocoaでプログラミングを始めて惑ったことのひとつに
座標系(Cordinate system)がWindowsなどと違うことだ。
多くの言語では画面上の座標の原点は左上隅にあり、
垂直方向の座標は下に行くほど大きくなる。
Cocoaでは原点は左下にあり、垂直方向に上にいくほど座標が
大きくなる。(これは数学や、日常的な座標系とおなじである。)
とはいえ、このこと自体は慣れると思う。

ただ、左下隅が原点であるということによる不都合もある。
スクロールビュー(NSScrollView)の中に表示するビュー(NSViewなど)
がデフォルトでは左下隅にくっついてしまうのだ。

外側の青い部分がスクロールビュー
内側の白い部分が内容を表示するビュー






この状態では、アプリケーションの使い勝手が悪くなってしまう。
これをこういう状態になおしたい。


この場合、内側のビュー(NSViewなどを継承したビュー)
のクラスにて isFlipped をオーバーライドし、戻り値としてYESを返すようにするだけでよい。
- (void)isFlipped{
    return YES;
}




ビューに直接描画しているのであれば、これでOKなのであるが、
いったんレイヤー(CGLayer)に描画してからビューに投影している
ような場合、不都合が残っている。


左図のように鏡で上下が逆さまになった状態となってしまう。
レイヤーはFlip(上下反転)していないままそこに Hello と描画している。そのレイヤーをFlipされたビューに描画する際にひっくりかえるのだ。


よって、レイヤーもFlipしておく必要がある。
レイヤーに描画する前にそのコンテキストに対して以下を施す。



CGContextTranslateCTM(layerContext, 0, layerHeight );

CGContextScaleCTM(layerContext, 1, -1);


一つ目で、原点を垂直方向に移動させる座標変換がコンテキストに登録され
二つ目で、垂直方向の座標の符号を逆転する座標変換が登録される。
例えば横幅100 x 縦100 のサイズを持つレイヤー上の
座標(10, 20) はFlip(上下反転)すると
一つ目の変換では 座標(0, 100) を原点とした場合の座標に変換されれるので
(10, -80) となる。
二つ目の変換では垂直方向の符号を逆転するので、(10, 80) となる。

※つまり下から20ポイントの場所は高さ100ポイントの場所からみると
下に向かって80ポイントの場所にあたるということである。

このようにしてFlipされたレイヤーには上下反転して描画される。
そのレイヤーをFlipされたViewに描画すると、さらに上下反転され
正常な状態で表示される。

金曜日, 9月 02, 2011

COCOA備忘

これは自分のための備忘です。すみません。


  • Resources フォルダのファイルパスをプログラム実行時に取得するコード
    • [[NSBundle mainBundle] pathForResource:@"filename" ofType:@"extension"]

  • CGLayer上にテキストを出力する方法。
    NSViewなどに出力する時はNSStringのdrawInRectが使えるが、CGLayerに出力するケースには使えない。この場合CoreTextを使う方法が簡単そうであった。
    • NSAttributedStringを生成
      NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:@"こんにちは" attributes:fontAttributes]; 
    • CTLineCreateWithAttributedStringを使って CTLineRefを生成
      CTLineRef line = CTLineCreateWithAttributedString((CFAttributedStringRef)attrStr);
    • CGContextSetTextPositionを使って出力位置を指定
      CGContextSetTextPosition(context, pt.x, pt.y);
    • CTLineDrawを使って文字を出力
      CTLineDraw(line, context);
    • メモリの解放
      CFRelease(line);
      [attrStr release];

  • イメージの特定の色を透過させる方法。
    このような処理を Maskingと呼ぶ。
    rect はNSRect型で表示したい場所をさしている。
    ctx はグラフィックコンテキストをさしている。
    • 元のイメージが NSImage *nsimg に生成済みだとする。
      これからCGImageRefを取得する。
      CGImageRef cgimg = [nsimg CGImageForProposedRect:&rect context: ctx hints: [[NSDictionary alloc] init]];
    • マスキングカラーを設定する
      CGFloat maskingColors[6] = {255,255,255,255,255,255};
      //左から二つずつ組となりそれぞれR,G,Bの範囲を示している。
    • マスキングをかけたイメージを生成する
      CGImageRef maskedImage = CGImageCreateWithMaskingColors(cgimg, maskingColors);
    • コンテキストに描く
      CGContextDrawImage(ctx, rect, maskedImage);

金曜日, 8月 26, 2011

Cocoa

去年の暮れに iMacを買いました。
これまでずっとWindows一辺倒だったのですが、
なんかインターフェースがすっきりしているというか
洗練されているところに惹かれてiMacにしました。
WindowsXP以降インターフェースのデザインが
だんだん野暮ったくなっているような気がします。

まあWindowsはおいといて、今後はMacでアプリを作ってみたいぞ
というわけで、時間を見つけてはAppleのフレームワークである
Cocoaの学習をしています。
年末に「Mac OS X Cocoa プログラミング」という本を買いました。

本当はある程度集中して、読み進めた方がいいのですが、
仕事の合間に、ちまちまと読みすすめてきたので、今週になって
やっとほぼ読み終わったところです。
でも、この本はObjective-Cも初めて、Macも初心者という私にはちょうど
とりかかりやすいものでした。

今週から、自分の作りたいようにいろいろ試しています。
いつもそうですが、教科書のサンプルコードを書いて試しているうちはいいですが
いざ、自分でこれをしようとか思った時には、まごつきます。
教科書に載っていたことも忘れているし、やりたいことがその教科書に
載っているとも限りません。
幸い、XCodeに附属のドキュメントはとてもよく出来ているようです。

これからが本当の始まりです。楽しみがいっぱいです。