XCodeに「リサーチアシスタント」なるものが追加されていた。
コード中、メソッドなどを選択するとそれに関連する情報が表示されるようになる。出し方はメニュー「ヘルプ > リサーチアシスタントを表示」を使う。
関連APIや関連ドキュメントの表示は役立ちそう。
なお「抽象」は「要約」(abstract)の誤訳では?英語版を見ていないのでわからないが。
2008年2月19日火曜日
Xcode - リサーチアシスタント
2008年2月18日月曜日
NSTrackingArea
前回に引き続きマウスとラッキングの検証。
MacOSX10.5より NSTrackingArea が追加された。解説が ADCのドキュメントにある。
Using Tracking-Area Objects
早速サンプルを作ってみた。
NSTrackingAreaSample.zip
サンプルの動作は前回同様、ビューの領域にマウスカーソルが入ると色が変わるというもの。
さて以前のトラッキングとどう変わったかというと...
・トラッキングに関する情報が1つのクラスにまとめられた
・トラッキングオプションで受け取るイベントや振る舞いを設定することができるようになった
・トラッキング登録のメソッドが addTrackingRect:owner:userData:assumeInside: から addTrackingArea: に変更された。登録のタイミングが緩和され initWithFrame: でも良くなった。
・ビューの大きさが変更になると updateTrackingAreas が送られるようになった。これを使い、トラッキング領域の再設定ができる。
トラッキングオプションはリファレンスマニュアルに説明がある。
NSTrackingArea Class Reference
登録部分のコード例を示す。
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
_mouse_status = 0;
_tracking_area = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveInKeyWindow | NSTrackingEnabledDuringMouseDrag )
owner:self
userInfo:nil];
[self addTrackingArea:_tracking_area];
}
return self;
}これだけで mouseEntered:, mouseMoved:, mouseExited が送られてくるようになる。これまでの方法と違って mouseEntered: と mouseExited: の中で setAcceptsMouseMovedEvents: を呼ぶ必要もなく、登録タイミングも initWithFrame: 内で良いのでわかりやすい。トラッキング情報を1つのクラスにまとめることでトラッキングに関する個所がシンプルになった。悪くない。
なおビューを NSScrollView の中で使う場合はオプションに NSTrackingInVisibleRect を指定すると表示領域のみがトラッキング対象となるので使いやすい。
2008年2月17日日曜日
マウス移動のトラッキング
NSViewではマウス移動をトラッキングすることができる。トラッキングを使えば画像の上にマウスカーソルを置いた時に反転表示したり枠線を付けたりすることができる。
トラッキングの動きを見るサンプルを作ってみた。
MouseTrackingSample.zip
マウスをWindow内の灰色の部分へ移動させると白色に反転する。
トラッキングを開始すると次のメッセージを受け取ることができるようになる。
mouseEntered:
mouseMoved:
mouseExited:
ただしデフォルトではこれらのメッセージが飛ぶことはなく、いくつかの準備が必要。やり方は ADCのドキュメントに書いてある。
Handling Mouse-Tracking Events
(1) mouseEnteredとmouseExited
まずトラッキングイベントの受け取り登録を NSView#addTrackingRect:owner:userData:assumeInside: を使って行う。ドキュメントによれば initWithFrame: ではなく、viewDidMoveToWindow: 内で行うのが良いとのこと。
- (void)viewDidMoveToWindow {
tag = [self addTrackingRect:[self bounds] owner:self userData:NULL assumeInside:NO];
}これで mouseEntered: と mouseExited: がこのビューへ送られるようになる。
(2) mouseMoved:
mouseMoved: メッセージを受け取るにはこれらに加えてさらに親ウィンドウに setAcceptsMouseMovedEvents:YES を送る必要がある。デフォルトではイベント量が多く、余計な負荷となってしまう為にこの設定が NOになっている。mouseEntered: でマウスがトラッキング領域に入ったところでこのメッセージを送る。すると mouseMoved: メッセージが送られてくるようになる。そのままだとメッセージが送られ続けるのでマウスカーソルが外に出た時点、つまり mouseExited: が送られた時点で NOを設定する。
その他、わかったこと:
- ビューがファーストレスポンダでないと mouseMoved:が送られない。mouseEntered: の中で [[self window] makeFirstResponder:self]; としてやる。
- moueMoved: はマウスを押している(ドラッグしている)間は発生しない。これは ADCドキュメントにも書かれている。
なおビューの大きさが変わった場合はこれに合わせてトラッキング領域も変更する必要がある。setFrame: と setBounds: にトラッキング領域を再設定するコードを書いておく。
- (void)setFrame:(NSRect)frame
{
[super setFrame:frame];
[self removeTrackingRect:tag];
tag = [self addTrackingRect:[self bounds] owner:self userData:NULL assumeInside:NO];
}
- - - -
MacOSX 10.5からは NSTrackingAreaが新しく導入されている。
Using Tracking-Area Objects
この検証はまた後日。
2008年2月16日土曜日
HUDを探して...
HUD ( Heads Up Display )とは Appleのアプリケーションでよく使われている黒い半透明のパネルのこと。
Interface Builder 3.0でも使われているこんなやつ。
iPhoto の例
Interface Builder3.0から HUD Window というオブジェクトが追加されている。
実体は NSPanel で Style に新たに追加された NSHUDWindowMask を指定する。Interface Builderでは HUDにチェックが入っている。
これを使うとこんな感じになる。
ただ難点があって、その上に載せるボタンなどのコントロールが Aqua(もしくはメタル、テクスチャ)表現のみしかない。この為、Appleのソフトと違ってちょっと違和感のある表示になってしまう。
ボタンなどのコントロール類を HUD表示に替える方法を探したが、残念ながら見つからなかった。他にも同様に探している人もいるようだが、どうも Appleの方から(今のところは)公式に提供はされていない様子だった。
関連リンク:
HUD Controls in Leopard
Re: HUD controls
そんな中、何人かの人が独自にコントロールを作ったりしている。
(1) iLife Controls; HUD windows and more
提供されていたサンプルをビルドして実行した結果が下のウィンドウ。これはなかなか良い。
コントロールはパスで描画しているのではなく TIFF画像であらかじめ用意したものを表示しているようだ。
利用ライセンスは不明。
日本語での紹介ページ:
iLifeControls.frameworkの使い方(きりかリポーツ)
(2) HMBlkAppKit
HMDTで提供されているフレームワーク。修正BSDライセンスでライセンス表記等があれば自由に利用できる。元々はシイラプロジェクトで作られたもののようだ。
- - - -
せっかく HUD Window が提供されているのに、それに合うコントロールが提供されていないのは残念。
しかし HUDは Appleの Human Interface Design の Guideline的にはどうなのだろうか。個人的には好きなデザインではあるが。
2008年2月15日金曜日
IKSlideshow
MacOSX 10.5 から手軽にスライドショーができる IKSlideshowが加わった。
IKSlideshow Class Reference
このクラスを使うとおなじみのスライドショーが数行のコードで作れてしまう。

さっそくサンプルを作ってみた。
サンプル:IKSSample.zip
ボタンを押すと壁紙(/Library/Desktop Pictures/*.jpg)のスライドショーが始まる。
書いたコードは MyControllerクラスのみ。
MyController.h
#import
#import
@interface MyController : NSObject{
NSMutableArray *_image_list;
}
-(IBAction)start:(id)sender;
@end
MyController.m
@implementation MyController
-(id)init .....(1)
{
self = [super init];
NSString* path = @"/Library/Desktop Pictures";
NSArray* array = [[NSFileManager defaultManager] directoryContentsAtPath:path];
_image_list = [[NSMutableArray alloc] init];
for (NSString* name in array) {
if ([[name pathExtension] isEqualToString:@"jpg"]) {
[_image_list addObject:[path stringByAppendingPathComponent:name]];
}
}
return self;
}
-(IBAction)start:(id)sender ...(3)
{
[[IKSlideshow sharedSlideshow]
runSlideshowWithDataSource:(id)self
inMode:IKSlideshowModeImages
options:nil];
}
- (NSUInteger)numberOfSlideshowItems ...(2a)
{
return [_image_list count];
}
- (id)slideshowItemAtIndex: (NSUInteger)index ....(2b)
{
return [_image_list objectAtIndex:index];
}
@end
(1) インスタンス初期化時(init)に /Library/Desktop Pictures/*.jpg のパス一覧を作り _image_listへ格納しておく。
(2a)(2b) IKSlideshowはスライドショーで表示する内容をデータソースから取得する。データソースは IKSlideshowDataSourceプロトコルで定義されている。画像数を返す numberOfSlideshowItems と 画像データ(ファイル名)を返す slideshowItemAtIndex: の2つを最低限実装する必要がある。
(3) ボタンが押されたら IKSlideshow のインスタンスへ メッセージ runSlideshowWithDataSource:inMode:options: を送る。するとスライドショーが始まる。
コードはこれだけ。データソースで提供するデータはファイル名でも良いし、NSImageでも良い。
IKSlideshow.h 抜粋
// export an item to the given application
// The item can be:
// - NSImage *
// - NSString * (path)
// - NSURL *
// - an NSArray of NSImage / NSString / NSURL
+ (void) exportSlideshowItem: (id) item
toApplication: (NSString *) applicationBundleIdentifier;
@end
ImageKitは他にもいろいろと面白いクラスがある。今回の IKSlideshowも含めてプログラミングガイドが ADCで出ている。
Introduction to Image Kit Programming Guide
ADCのサンプルプログラム
IKSlideshowDemo
木下さんによる紹介もあった。
LeopardのImage KitでiPhotoを作る--一手間加えてiPDF?も作っちゃおう
- - - -
これだけ簡単に利用できると画像や PDFを使うアプリでは今後ついてて当たり前の機能になるな。
2008年2月14日木曜日
スクラップブックその7 - 選択の表現を替える
画像が選択されていた時には枠線を表示していたが、グレーの半透明色で塗りつぶすように変更した。
WorkView.m
- (void)drawRect:(NSRect)rect {
[[NSColor whiteColor] set];
NSRectFill(rect);
for (Item* item in [_controller items]) {
[item.image compositeToPoint:NSMakePoint([item.x floatValue],
[item.y floatValue]+[item.height floatValue])
operation:NSCompositeSourceOver];
if (_selected_item == item) {
// draw selection
[[[NSColor grayColor] colorWithAlphaComponent:0.3f] set];
[NSBezierPath fillRect:[item rect]];
}
}
}画像を描画した上に半透明色で上書きする。NSColor の colorWithAlphaComponentを使うと半透明色で描画ができる。
それと画像以外の個所をクリックした時に選択を外すようにした。現状ではメンバ変数 _selected_iem = nil だけで良い。
2008年2月13日水曜日
スクラップブックその6 - サイズ固定と自動スクロール
前回のスクラップブックでドラッグにあわせて Viewのサイズを変えたが、使いづらいのでサイズを固定することにした。
mouseDown: の中で呼出していた resizeWithRect: をコメントアウトし、InterfaceBuilderで WorkViewのサイズを(1000,1000)、Windowの最大サイズを (1000,1000)にした。
Viewが広くなったのでスクロールしていろいろな場所に画像を配置することができる。どうせなら画像をドラッグして画面の端へ移動させた時に自動的にスクロールするようにしたい。
Viewにはこれを簡単に行うことのできる便利なメソッドが用意されている。
[NSView autoscroll:]
このメッセージを NSViewへ送ると、外側の NSScrollView がこれを適切に処理してくれる。
Supporting Automatic Scrolling
ドラッグ処理に1行加える。
WorkView.m
- (void)mouseDown:(NSEvent *)theEvent
:
while (1) {
theEvent = [[self window] nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
current_point = [self convertPoint:[theEvent locationInWindow]
fromView:nil];
[self autoscroll:theEvent]; // <--追加
:
Cocoaは良くできている...感心。
