ページ

2009年6月30日火曜日

iPhone本

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

また新しい iPhoneプログラミング本。

立ち読みした限りでは良い感じがする。
ありがちなリファレンス本ではなく目的に沿って必要な技術のみを解説をするタイプ。
ヒガレス本の iPhone版といった印象をうけた。





iPhoneプログラミングを始めるにあたって1冊欲しいと思っていたところなので購入を検討中。

PS. 週末にiPhoneをゲット。これは楽しい。
24時間インターネットにつながる環境というのはちょっとすごいかも。

2009年6月29日月曜日

ホットキー変更対応(16) - 設計

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

検証が大体できてきたので SimpleCapへの組み込みを始めよう。

組み込みにあたり、実際の動作パターンを整理してクラスを設計してみる。使い方のパターンは4つが考えられる。

(1) ホットキーの初期登録


アプリケーション起動時にUserDefaultsの値を使い、ホットキーをシステムへ登録する。


(2) ホットキーの表示


ユーザがプリファレンスを開いた時にUserDefaultsの値を文字列に変換して表示する。


(3) ホットキー入力


ユーザが入力したホットキーをシステムおよび UserDefaultsへ登録する。最後に文字列に変換して表示する。


(4) デフォルトに戻す。


ボタンが押されたら UserDefaultsをデフォルトに戻し、システムへホットキーを登録する。最後に文字列に変換して表示する。

こんなところか。

- - - -
CocoaBindings が使えるともう少し楽なのだが InterfaceBuilderが使えないので今回は自前でデータと表示を結びつける。ホットキー入力UIの部分に NSTextField で keyDown: が使えればいいのだが、その後も調べたが良い方法は見つからなかった。最終的には今まで見てきた様に NSTextView を使う。

2009年6月28日日曜日

NSString 文字列へ Unicode を埋め込む

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

\u を使う。

例:
NSLog(@"\u232b");


こうなる。


それだけ。

2009年6月27日土曜日

ホットキー変更対応(15) - 入力ルールを調整

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

キーの入力ルールを調整する。

システム環境設定では大体次のようになっていた。

・Shift + キーは受け付けない
・Command + キーは OK
・Option + キーは OK
・Control + キーは OK
・Shiftは他の Command, Option, Control との組み合わせなら OK
・Escapeキーは他の Command, Option, Control との組み合わせなら OK
・Returnキーは他の Command, Option, Control との組み合わせなら OK
・入力中に Escapeキーを押すとキャンセル

その他、Deleteは不可など。

独自にルールを決める必要も無いので、上記に従う様にした。

Deleteなどキー毎に使えるかどうかの判断は以前定義した構造体のパラメータで判断する。

static const struct {
UInt32 keycode;
NSString* description;
NSString* string;
BOOL is_hotkey;
}
@"Unkown" , NO },
{ kVK_ANSI_A , @"A" , @"A" , YES },
{ kVK_ANSI_S , @"S" , @"S" , YES },
:


最後の is_hotkeyがそれ。


それ以外のルールはロジックを組み込む。

TextView.m
-(void)keyDown:(NSEvent *)theEvent
:
if (!(modifier & (cmdKey | optionKey | controlKey))) {
if (key == kVK_Escape) {
[self redraw];
[self endEdit];
}
// abort
return;
}

if (![KeyCharMapper isHotKeyForKeyCode:key]) {
// abort
return;
}
:

2009年6月26日金曜日

iPhone本(洋書)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

本屋に行くとまた iPhone開発本が出ていた。




そろそろ iPhoneプログラミングをやろうと考えてぼちぼち調査を初めている。
本屋へ行って色々と本を眺めているのだが初心者向けが多いせいかなかなか知りたい情報が無い。
このあたりはやはり自分でやっていくしかないか。

- - - -
今日は iPhone3Gs を入手予定。初 iPhoneなのでちょっとワクワクしてる。

2009年6月25日木曜日

ホットキー変更対応(14) - ダブルクリックで設定モードへ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

キー入力の基本ができたので、次は実際の設定インターフェイスを作り込んでいく。

動作は次のようにする。
(1) NSTextViewへホットキー初期設定を表示する。
  この時点ではキー入力を受け付けない。

(2) NSTextViewをダブルクリックすると
  キー入力を受け付けるようになる。
  この時、表示されている文字を変更可能であることが
  わかるように選択状態にする。

(3) キーを入力するとその値を表示し、
  再びキーを受け付けないようになる。


キーを受け付けるモードを管理する為にメンバ変数を追加する。
TextView.h

@class HotkeyFormatter;
@interface TextView : NSTextView {
IBOutlet HotkeyFormatter* _hotkey_formatter;
NSNumber* _hotkey;

BOOL _is_editing; // キー受付モード
}



キー受付開始と終了時の処理を受け持つメソッドをそれぞれ追加する。
TextView.m
- (void)startEdit
{
[[self window] makeFirstResponder:self];
[self setSelectable:YES];
_is_editing = YES;
NSRange range = NSMakeRange(0, [[self string] length]);
[self setSelectedRange:range];
}


- (void)endEdit
{
[self setSelectable:NO];
_is_editing = NO;
}


startEdit では TextViewをファーストレスポンダにしてキー入力を受け取れるようにする。また現在の設定値(文字列)を選択状態にする。

endEdit では入力モードをオフにする。


ダブルクリックされたら startEdit を呼び出す。
- (void)mouseDown:(id)theEvent
{
if ([theEvent clickCount] >= 2) {
[self startEdit];
}
}


後は前回のコードとほぼ同じ。
入力モードがオフの場合はキー入力を受け付けない処理だけ書いておく。
- (void)keyDown:(NSEvent *)theEvent
{
NSLog(@"%@", theEvent);

if (!_is_editing) {
return;
}
:


この辺りの動作は以前ファイル名の変更の時にも書いた。詳細は下記を参照のこと。
ファイル名変更(その3)テキストボックス CommentsAdd Star



さて動かしてみよう。

まず実行直後は初期設定が表示される。


ダブルクリックすると入力モードがオンになる。


そこでキーを入力すると、入力キーが表示され、入力モードがオフとなる。



サンプル:HotKeyUI-3.zip

- - - -
だんだん形になってきた。

2009年6月24日水曜日

ホットキー変更対応(13) - キー入力を表示

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

さて下準備ができたのでいよいよ入力キーを表示させてみる。

まず今までの検証コードを少し削除して必要なものだけ残す。インターフェイスは NSTextViewだけ残す。


コードはサンプルを参照のこと。

サンプル:HotkeyUI-2.zip

基本的には今まで紹介した内容を組み合わせただけで特別なことはやっていない。



さて実行してみよう。

まずは Commandキーを押しながら D (※深い意味は無い)


出た。

次は修飾キー全部押し。Control + Option(Alt) + Command + Shift + 'H'


おお出た。ちょっとうれしい。

特別なキーもこの通り。

Deleteキー


矢印


Returnキー



なお '@'(すなわち Shift + '2')は次のように表示される。


表示文字ではなくキーを判定するのでこれで良い(と思う)。

2009年6月23日火曜日

ホットキー変更対応(12) - InterfaceBuilderでNSTextViewを配置する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

InterfaceBuilderを使い NSTextViewを配置してみる。パレットに NSTextViewは無いのだが Custom View を使えばできることがわかった。

まず Interface Builder で Custom View を配置する。


このクラスに前回用意した TextView を指定する。


実行してみよう。


出た。
こうするとわざわざプログラムコードで生成や面倒な位置決めを行う必要がなくなる。この方法は NSViewのサブクラスなら何でも使えそうだ。

2009年6月22日月曜日

ホットキー変更対応(11) - キー入力を捉える (NSTextView)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

IntefaceBuilderではテキストボックス関連のクラスはすべて NSTextFieldが割り当てられている。



通常の用途ではこれで良いのだが、今回のような用途ではオーバスペックで逆に使いづらい。やりたいのは下記のこと。
 ・キー文字の表示
 ・キー入力のハンドリング
 ・レスポンダーになれる

NSTextFieldの場合、入力された「文字列」を扱うのは便利なのだが「キー値」が扱えない。NSTextFieldの派生クラスを作っても - [NSResponder keyDown:] が呼ばれないから。

NSTextFieldで入力キーを扱う方法には、以前紹介した(ファイル名変更(その4)NSTextFieldでESCキーをハンドリングする CommentsAdd Star)、デリゲートメソッド - [NSTextField control:textView:doCommandBySelector:] があるが、特定の文字だけのハンドリングならともかく、ほとんどすべての文字を対象にするには十分でない。


そこで NSTextFieldではなく、その下請けにあたる NSTextView クラスを試してみる。InterfaceBuilderからは作れないようなので、プログラムコードからインスタンスを生成する。

まず NSTextView のサブクラスを定義する。
TextView.h

@interface TextView : NSTextView


キーイベントをデバッグコンソールへ出力させる。
TextView.m
@implementation TextView

- (void)keyDown:(NSEvent *)theEvent
{
NSLog(@"%@", theEvent);
}


このクラスのインスタンスを AppControllerで作成し、ウィンドウへ貼付ける。
AppController.m
- awakeFromNib
{
_text_view = [[TextView alloc] initWithFrame:NSMakeRect(10,10,100,25)];
[[_window contentView] addSubview:_text_view];
[_window makeFirstResponder:_text_view];
[_text_view insertText:@"Hello"];
}


実行してみよう。


NSTextView の上でキーボードをたたいてみる。

2009-06-22 22:29:20.225 HotkeyUI[7058:10b] NSEvent: type=KeyDown loc=(0,119) time=134100.3 flags=0x20102 win=0x0 winNum=15724 ctxt=0x1515f chars="A" unmodchars="A" repeat=0 keyCode=0
2009-06-22 22:29:21.040 HotkeyUI[7058:10b] NSEvent: type=KeyDown loc=(0,119) time=134101.2 flags=0x20102 win=0x0 winNum=15724 ctxt=0x1515f chars="B" unmodchars="B" repeat=0 keyCode=11
2009-06-22 22:29:23.089 HotkeyUI[7058:10b] NSEvent: type=KeyDown loc=(0,119) time=134103.2 flags=0x100108 win=0x0 winNum=15724 ctxt=0x1515f chars="c" unmodchars="c" repeat=0 keyCode=8


- [NSResponder keyDown:] が呼ばれた。

なお入力された文字は NSTextView には反映されない(何を入力しても初期表示 "Hello"のまま)。今回表示は自前で対処するのでこれは好都合。よしこれで進めていこう。

2009年6月21日日曜日

ホットキー変更対応(10) - キー入力値と表示文字の変換表を作る

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

結局、キー入力値と表示文字(文字列)の対応表を作る事にした。
キー値は Event.h の値を使うことにする。これは現在のホットキー実装が Carbonを使っているから。

まずは Cの構造体でソースへ埋め込むことにする。
こんな感じ。

static const struct {
UInt32 keycode;
NSString* description;
NSString* string;
BOOL is_hotkey;
}
keymap[] = {
{ kVK_ANSI_A , @"A" , @"A" , YES },
{ kVK_ANSI_S , @"S" , @"S" , YES },
{ kVK_ANSI_D , @"D" , @"D" , YES },
{ kVK_ANSI_F , @"F" , @"F" , YES },
:


最初のkeycodeは Event.h で定義されているキー値。続く descriptionはデバッグ用の説明文字列。3番目は画面表示用の文字列。そして最後はホットキー利用の可否を表すフラグ。

定義されているキーはすべて使えるわけではなく、例えばエスケープキーなどは使えない。これを判断するために is_hotkey を設けてある。

- - - -
さて、これを使って入力キー値を表示させようとするが NSTextFiledが keyDown: を受け取れないことを思い出した。これは困った。さてどうするか。

2009年6月20日土曜日

ホットキー変更対応(9) - AppleSpecificCodePoints を試す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回紹介した AppleSpecificCodePoints を実際に表示させてみた。

CocoaDev: AppleSpecificCodePoints

コードはこんな感じ。

static const struct { NSString* name; unichar code; } KeyGlyphs[] =
{
{ @"pb_enter", 0x2324 },

{ @"left", 0x2190 },
{ @"up", 0x2191 },
{ @"right", 0x2192 },
{ @"down", 0x2193 },

{ @"ib_left", 0x21E0 },
{ @"ib_up", 0x21E1 },
{ @"ib_right", 0x21E2 },
{ @"ib_down", 0x21E3 },

{ @"home", 0x2196 },
{ @"end", 0x2198 },
{ @"return", 0x21A9 },
{ @"pageup", 0x21DE },
{ @"pagedown", 0x21DF },
{ @"tab", 0x21E5 },
{ @"backtab", 0x21E4 },
{ @"shift", 0x21E7 },
{ @"control", 0x2303 },
{ @"enter", 0x2305 },
{ @"command", 0x2318 },
{ @"modifier", 0x2325 },
{ @"backspace", 0x232B },
{ @"delete", 0x2326 },
{ @"escape", 0x238B },
{ @"numlock", 0x2327 },
{ @"help", 0x225F },
};

- (void)awakeFromNib
{
for(int i=0; i < sizeof(KeyGlyphs)/sizeof(KeyGlyphs[0]); i++) {
NSLog(@"0x%x : %C : %@", KeyGlyphs[i].code, KeyGlyphs[i].code, KeyGlyphs[i].name);
}
}


実行してみよう。

デバッガコンソールへ出力された結果は次の通り。



なるほど一通り揃っているようだ。

- - - -
キー値を文字コードに変換する関数もあるようだが、今のところ分かった限りでは最低でも特殊キー(ESCや矢印)は自前で表(キーコード対Unicode)を用意する必要がありそうだ。
となると以前紹介したように始めから全コードを対象にした表を持っていた方がいい気がしてきた。

2009年6月19日金曜日

ホットキー変更対応(8) - 入力キーを表示文字へ変換するには?

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

入力されたキーコードを表示用の文字コードに変換する方法についてネットで調べてみた。


これはまさに同じ問題を扱っている。問題解決の参考になる URLが紹介されている。
Cocoabuilder - KeyTranslate and UCKeyTranslate question

ここでは特殊な文字については自前でUnicode Character Pointの配列を用意する方法が紹介されている。
Cocoabuilder - Re: Key codes and characters in NSEvents

上記で紹介されていた方法をまとめたもの。サンプルコードもある。
CocoaDev: AppleSpecificCodePoints

Glyph Access Protocol についての解説(Unicodeに含まれない unencodedな Glyphについて)。
Technical Note TN2079: Glyph Access Protocol

Carbon’s HIToolbox framework に含まれる Text Input Serviceのリファレンス。前回はこの中の関数を使った。
Text Input Source Services Reference

その他、参考で。
Unicode Utilities Reference

- - - -
うーむ。
キーの表示くらい簡単に行くかと思っていたが奥が深い。。

2009年6月18日木曜日

ホットキー変更対応(7) - キーを表示する(その2)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回紹介した方法では入力キーを表現する為に plistで文字を用意していた。
SimpleCapでもその方法を取ろうかと思ったが、APIぐらいあるんじゃないかとも思い調べてみた。

すると情報があった。

Cocoa-dev - virtual keycode to character

この情報によると Carbonで用意されている関数を使うと入力キーを文字表現に変換することができるらしい。

早速試してみよう。幸いソースコードもこのメーリングリストに出ている。
Re: virtual keycode to character


こんな感じになった。デバッガコンソールへ表示するようにしてある。
AppController.m

- (void)awakeFromNib
{
UInt32 key = 29; //'0'
UInt32 dead_key_state = 0;
UniCharCount count = 0;
UniChar base_char;

TISInputSourceRef source_ref = TISCopyCurrentKeyboardLayoutInputSource();
CFDataRef unicodekey_layout_ref = (CFDataRef)TISGetInputSourceProperty(source_ref, kTISPropertyUnicodeKeyLayoutData);
CFRelease(source_ref);

UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(unicodekey_layout_ref),
key,
kUCKeyActionDown,
0,
LMGetKbdType(),
kUCKeyTranslateNoDeadKeysBit,
&dead_key_state,
1,
&count,
&base_char);
NSLog(@"%C", base_char);}



実行してみよう。キーコード 29 は '0'と表示されるはず。
[Session started at 2009-06-18 22:25:17 +0900.]
2009-06-18 22:25:19.105 HotkeyUI[1667:10b] 0


出た。'0'だとわかりずらいので他のコードを試してみよう。

'c' (0x08)はどうだ。
[Session started at 2009-06-18 22:27:58 +0900.]
2009-06-18 22:27:59.200 HotkeyUI[1727:10b] c


出た。

TABキー (0x30)はどうだ。
[Session started at 2009-06-18 22:31:15 +0900.]
2009-06-18 22:31:17.820 HotkeyUI[1827:10b]


出ない。

ESCキーなど特殊なキーの場合は特別文字が割り当てられないようだ。

2009年6月17日水曜日

ホットキー変更対応(6) - キーを表示する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

前回修飾キーまでは表示することができた。後は通常のキーを表示するのだが、イベント判別用にキーに割り当てられているコードと、画面表示用に割り当てられるキャラクターコードが異なっている。これをなんらか変換してやる必要がある。

以前紹介したソースコードを見ると変換用のテーブルを言語とに plist で持っていた。
下記は japanese.lproj 下の PTKeyCodes.plist。他に English.lproj や Frentch.lproj などが用意されていた。


なるほど。これならキー表現をローカライズして提供できる。

なおこのキーの割当(0 => 'A')は Events.h (Carbon)の中で定義されている。
Events.h

enum {
kVK_ANSI_A = 0x00,
kVK_ANSI_S = 0x01,
kVK_ANSI_D = 0x02,
kVK_ANSI_F = 0x03,
kVK_ANSI_H = 0x04,
:
:


さて今回はどうするか。

2009年6月16日火曜日

ホットキー変更対応(5) - 修飾キーを表示する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

入力は後回しにして先に表示を片付けよう。

まずは表示確認用にcommand+option+0 を表す値を NSUserDefaultsへ固定で入れておく。これが画面上 command option 0 (それぞれ記号)で表示されれば良い。

表示確認用の値は - [AppController awakeFromNib]で設定する。

AppController.m

- (void)awakeFromNib
{
UInt32 modifier = optionKey | cmdKey;
UInt32 key = 29; //'0'

UInt32 hotkey = (modifier << 16) | key;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithUnsignedInt:hotkey] forKey:@"hotkey"];
}


NSUserDefaults には Unsinged Int 32ビットで格納し、上位 16ビットを修飾キーに、下位 16ビットを通常キーに割り当てる。


実行すると10進数値が表示される(※16進数値では 0x9000001d)。



次はこの値から修飾キー表示用の文字列を作成する。前回用意した [HotkeyFormatter stringForObjectValue:] にこの処理を書く。

HotkeyFormatter.m
- (NSString *)stringForObjectValue:(id)anObject
{
NSString* key_desc = @"";
if (anObject && [anObject isKindOfClass:[NSNumber class]]) {
UInt32 value = [anObject unsignedIntValue];
UInt32 modifier = value >> 16;
UInt32 key = value & 0xff;

NSLog(@"mod=%x", modifier);
NSLog(@"key=%x", key);

if (modifier & controlKey) {
key_desc = [key_desc stringByAppendingFormat:@"%C", kControlUnicode];
}
if (modifier & optionKey) {
key_desc = [key_desc stringByAppendingFormat:@"%C", kOptionUnicode];
}
if (modifier & cmdKey) {
key_desc = [key_desc stringByAppendingFormat:@"%C", kCommandUnicode];
}
if (modifier & shiftKey) {
key_desc = [key_desc stringByAppendingFormat:@"%C", kShiftUnicode];
}
}
return key_desc;
}


実行してみよう。




出た。

- - - -
修飾キーは表示できたので、後は実際のキー(今回は '0')を表示するのだが、これを表示するにはどうしたら良いのだろうか。キーボードの'0'を表す 29 (0x1d)は '0'のキャラクターコード 48 (0x30) では無い。変換する必要があるな。

2009年6月15日月曜日

ホットキー変更対応(4) - 設定画面を試作する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

サンプルアプリを試作してホットキー設定画面を試作してみる。

まずこんなウィンドウを作る。


設定キーを文字列表現させたいので、モデル(NSUserDefaults)の値を加工するフォーマッタ HotkeyFormatter を用意する。

HotkeyFormatter.h

@interface HotkeyFormatter : NSFormatter {
}

@end


HotkeyFormatter.m
@implementation HotkeyFormatter

- (NSString *)stringForObjectValue:(id)anObject
{
NSString* key_desc = [anObject description];
return key_desc;
}

- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
{
*anObject = string;
return YES;
}
@end


実装は後で行う。現在は動作確認用にメソッドだけ用意しておく。


これを InterfaceBuilder上でインスタンス化しておき、テキストボックスの Formatterアウトレットへ接続する。


こんな具合になる。


Cocoaバインディングを使い、入力した値を NSUserDefaults で管理させる。


実行して文字を入力するとそれがそのまま表示される。
入力した文字列はアプリを再起動すると復元される。



ベースができたので次回は NSUserDefaultsへ格納されたホットキーの値を表示させる処理を実装する。

2009年6月14日日曜日

ホットキー変更対応(3) modifieierキーの表現

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

commandキーやoptionキーなどを表現する必要があるが、これはどうやって表示するのだろうか?


いろいろ調べているとホットキーを扱うライブラリがあった。
Homegrown Developer Tools

ソースコードが配布されており中を見ると参考になるコードが見つかった。
PTKeyCombo.m

+ (NSString*)_stringForModifiers: (long)modifiers
{
static unichar modToChar[4][2] =
{
{ cmdKey, kCommandUnicode },
{ optionKey, kOptionUnicode },
{ controlKey, kControlUnicode },
{ shiftKey, kShiftUnicode }
};
:


なるほど文字コードが割当られていて定数定義されているのか。
サンプルアプリを作って試してみる。

AppController.m
#import "AppController.h"
#import <Carbon/Carbon.h>


@implementation AppController

- (void)awakeFromNib
{
NSLog(@"%C", kCommandUnicode);
NSLog(@"%C", kOptionUnicode);
NSLog(@"%C", kControlUnicode);
NSLog(@"%C", kShiftUnicode);
}

@end


デバッガコンソールへ4種類のmodifierキーを表示させる。実行してみよう。


出た。
よしこれを使おう。


参考
HotKeysLib3 - Cocoaでホットキー

2009年6月13日土曜日

SimpleCapバグ修正 - マルチスクリーン(2)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

マルチスクリーンの特定のケースでウィンドウキャプチャがおかしかった件が解決した(ウィンドウを選択した時に表示される画像がずれる)。
以前の対応で座標変換がもれていたのが原因。

座標変換を入れてやるとなおった。

-(NSImage*)image
{
if (!_image) {
NSRect rect = _rect;
rect.origin = [CoordinateConverter convertFromLocalToCGWindowPoint:rect.origin];
CGImageRef cgimage = CGWindowListCreateImage(NSRectToCGRect(rect),
//*old* CGImageRef cgimage = CGWindowListCreateImage(NSRectToCGRect(_rect),
 :



マルチスクリーンには手を焼かされた。

2009年6月12日金曜日

SimpleCapバグ修正 - マルチスクリーン

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

SYさんよりマルチスクリーンでバグがあるとの報告を受けた。
SimpleCap その後 〜コメント〜

マルチスクリーンでメニューバーが存在する画面のサイズが他よりも小さい場合に現象が発生する。例えば下記のケース。


以前、マルチスクリーンを手直した時にはこのケースは試していなかったので気がつかなかった。


調べると原因は [NSScreen mainScreen] の動作を誤解していることにあった。
NSScreen Class Reference - mainScreen

てっきりこのメソッドはメニューバーのある画面を返すものとばかり思っていたのだがそうではなく、リファレンスによるとキーボードイベントを受け付けるウィンドウが存在するスクリーンが "main screen"とのこと。

メニューバーを含むウィンドウは

The screen containing the menu bar is always the first object (index 0) in the array returned by the screens method. 

と書いてあった。つまり [NSScreen screens] で返される配列の最初のスクリーンがメニューバーを持つということ。そういえば以前読んだような気もする。


これらを元に座標系変換の実装を下記のように修正した。
(誤) NSRect m_frame = [[NSScreen mainScreen] frame];
(正) NSRect m_frame = [[[NSScreen screens] objectAtIndex:0] frame];



これでなおった。やれやれ。
座標変換のロジックが間違ってなかっただけ良かった。


SimpleCapにおけるマルチスクリーンでの座標変換ロジックはこのあたりで紹介している。
β版バグ修正 - マルチスクリーン
β版バグ修正 - マルチスクリーン(その2)

- - - -
直しているうちに別のバグを発見した。
やはりマルチスクリーンで利用している時にスクリーン配置の特定のケースで、ウィンドウキャプチャの表示がおかしいことがわかった。

2009年6月11日木曜日

ホットキー変更対応(2) ユーザインターフェイス

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

ホットキーは1つだけなのでそんなに凝ったユーザインターフェイスは要らない。

システム環境設定のようなものでいいかな。

2009年6月10日水曜日

ホットキー変更対応(1) 仕様

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

SimpleCapのホットキー変更の要望対応に入る。

現行の仕様は、option+command+0 を押すとステータスバーのメニューが開く様になっている。このキーは固定で変更できない。これを変更もしくは無効にできるようにする。

やりたいことをまとめると:
1. ホットキーを自由に変更できる
2. 無効にできる
3. デフォルト(option+command+0)に戻せる

これを実現するには:
1. プリファレンスに変更用インターフェイスを用意する
2. プリファレンスの保存、復帰の実装を用意する
3. ユーザが変更した時に変更する(=直前のホットキーを解除し、新規に登録する)実装を用意する


細かい所は作りながら詰めていこう。

2009年6月9日火曜日

WebKit検証(36) - キャッシュをクリアする(成功)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(キャッシュクリアの続き)

NSURLCache を調べてみた。

NSURLCache Class Reference

まず以前のサンプルコードに "Dump Cache" と "Clear Cache" ボタンを追加する(右下)。


コードはこう。
AppController.m


- (IBAction)dumpCache:(id)sender
{
NSURLCache* cache = [NSURLCache sharedURLCache];
NSLog(@"currentDiskUsage: %d", [cache currentDiskUsage]);
NSLog(@"diskCapacity: %d", [cache diskCapacity]);
NSLog(@"currentMemoryUsage: %d", [cache currentMemoryUsage]);
NSLog(@"memoryCapacity: %d", [cache memoryCapacity]);
}

- (IBAction)clearCache:(id)sender
{
NSURLCache* cache = [NSURLCache sharedURLCache];
[cache removeAllCachedResponses];
}


実行してAppleのページを開いた後のキャッシュファイルの状態はこう。


"Dump Cache"ボタンを押すと、currentDiskUsage: の値が一致している。メモリは使っていないことがわかる。


次に "Clear Cache"ボタンを押してみる。


おお、サイズが小さくなった。

"Dump Cache" で確認。


しつこく sqlite3 コマンドでテーブルの中身を調べてみる。cfurl_cache_response と cfurl_cache_blob_data は空だ。


うまくいったようだ。

まとめ:
- WebView で開いたページのキャッシュは [NSURLCache removeAllCachedResponses] でクリアできる。
- ファイルは削除されない(SQLiteデータベースのレコードが削除される)


- - - -
長々と引っ張ったがやっとキャッシュをクリアすることができた。ちょっとうれしい。

2009年6月8日月曜日

キャッシュ調査(さらに続く)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

引き続き調査。NS系ネットワークライブラリを調べてみたところキャッシュに関する記述が出て来た。

URL Loading System

URL Loading System Overview - Cache Management

抄訳
・キャッシュはディスクとメモリを使う。
・キャッシュはアプリケーションごとに格納される。
・キャッシュは NSURLConnection もしくは NSURLDownload によって使われる
・キャッシュポリシーは NSURLRequest 初期化時に決められる
・NSURLCache クラスを使ってキャッシュサイズや、ディスク上の保存位置を設定できる
・NSCachedURLResponse を使うとキャッシュされたコンテンツへアクセスすることができる
・NSCachedURLResponse は NSURLResponse とコンテンツデータをカプセル化している
・現行は http/https のリクエストがキャッシュされる(httpsリクエストはディスクにキャッシュされることはない)
・NSURLConnection の connection:willCacheResponse: デリゲートメソッドを使って、キャッシュの挙動を制御することができる


Using NSURLConnection - Controlling Response Caching


Understanding Cache Access

-> NSURLRequest でキャッシュポリシー (NSURLRequestCachePolicy) を決める


WebKit、WebCore、ネットワークライブラリの解説はHMDT木下さんの資料が参考になる。
Web Kitプログラミング解説と、 その実例としての シイラプロジェクト紹介 (PDF)


で、NSURLCache に辿り着く。
これはまた明日。

2009年6月7日日曜日

キャッシュ調査(続く)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

HKさんより情報をもらう。

Pulling Content Out Of OS X Cache.db Files

WebCoreを調べるという助言ももらい引き続き調査。

調べるうちに WebCoreとは別に NSURLCache も浮上して来た。

Problem with WebKit and subclasses of NSURLCache in Leopard

Cocoaはやっぱり! / インターネットにアクセスしよう / Web Kit : DRAFT

iPhoneやiPhoneシミュレータ上でNSURLCacheクラスを使う

[webkit-dev] WebKit caching


NSURLCache Class Reference


- - - -
今日は時間切れ。
明日以降、NSURLCache を少し調べてみよう。

2009年6月6日土曜日

引き続きキャッシュ調査 / Cache.db

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

Cache.db は CFNetowrk が作成している、という情報を得るがよくわからない。

[webkit-dev] webkit cache

Re: Leopard and Cache.db files


CFNetwork にそれらしいメソッドも見つからないのだが。。

CFNetwork Reference Collection

CFNetwork Programming Guide

2009年6月5日金曜日

WebKit検証(35) - キャッシュをクリアする(方法みつからず)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

WebKitが作成したキャッシュの確認ができたが、これを消す方法がわからない。
メソッドが見つからず、ネット上にも情報が見つからない。
もしかして自分でキャッシュファイル Cache.dbを削除するのだろうか。
キャッシュファイルの位置が確実に決められれば、それもありかもしれない。
(現在は ~/Library/Cache 配下にてきる)

うーむ。
今日は進展なし。

2009年6月4日木曜日

Cocoaアプリケーションの「About」パネル作成(続き)

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

先日の投稿(Cocoaアプリケーションの「About」パネル作成)では著作権表示がうまくいかないところで終わっていた。その後、コメントをもらい InfoPlist.strings を書き換えれば良いことがわかった。

InfoPlist.strings を開き NSHumanReadableCopyright というエントリを追加する。


実行すると、出た。


せっかくなので日本語も試してみる。Japanese のローカリゼーションを追加し日本語に書き換える。


出た。


- - - -
なんのことは無い、前回紹介した Tec Note にちゃんとかいてあった。
Technical Note TN2179
Cocoaアプリケーションの「About」パネル作成

なおルールがあって『InfoPlist.stringsエントリがInfo.plistエントリに優先することに留意してください。』とのことらしい。多言語対応するなら InfoPlist.strings に記載する方法が必須になる。

2009年6月3日水曜日

SimpleCap その後

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

SimpleCapのバージョンアップについて大々的な拡張は今のところ考えていない。
ただ現時点で欲しい機能がいくつかあるので、当面はその辺りを少しずつやろうと思う。

今欲しいのは、
・SimpleViewerの印刷機能
・SimpleViewerの原寸大表示
・SimpleViewerのクリッピング


あと構想レベルで
・SimpleViewerのアノテーション機能(文字や矢印を書き込める)
・SimpleViewerのインデックス表示(複数ファイルを一覧できる)

ただこれらは時間がかかるので本当にやるかは未定。
(要望があれば、というのもある)

- - - -
Webキャプチャについては、いろいろ考えたのだが
別の単体アプリとして作ろうと思う。
理由の一つは SimpleCap のユーザインターフェイスになじまないから。
これは SimpleCap修正の合間をみて今後作っていく。

2009年6月2日火曜日

SimpleCap 正式版(1.0.0)リリース

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

SimpleCap 正式版(1.0.0)をリリースしました。


専用ページを用意したので詳しくはそちらを見てください。

MacOSX用スクリーンキャプチャ SimpleCap
http://xcatsan.com/simplecap/



- - - -
昨年の4月に開発開始の宣言をしてから今日のリリースまで1年2ヶ月。長かった。
α版、β版と使い、意見と感想を送って下さった方々ありがとうございました。

2009年6月1日月曜日

Cocoaアプリケーションの「About」パネル作成

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

「About」パネルとはメニューの「**について」から開くウィンドウのこと。

例えば Safariの場合はメニューに「Safariについて」がある。


これを開くとバージョンやコピーライトが表示される。


Aboutパネルの設定方法は ADCの Techniical Note に掲載されている。

Technical Note TN2179 - Cocoaア
プリケーションの「About」パネル作成

Technical Note TN2179 - (英語)

これによれば通常はプロパティリスト値が自動的に使われるとのこと。HTMLやRTFで表現できるほか、独自のNSViewを表示させることもできる。

試しに Copyright を書き換えてみた。


ビルドしてみる。



あれ?変わらない。