ページ

2009年7月9日木曜日

ホットキー変更対応(23) - キー設定UIの実装

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

さて次はホットキー設定のユーザインターフェイスを実装する。以前の検証で作った NSTextViewのサブクラスを持ってきて修正する。クラス名は HotkeyTextView。

HotkeyTextView.h

@class Hotkey;
@interface HotkeyTextView : NSTextView {

BOOL _is_editing;
Hotkey* _hotkey;
}

- (Hotkey*)hotkey;
- (void)setHotkey:(Hotkey*)hotkey;

@end

setHotkey: は再描画処理を書きたいのでプロパティを使わず自前で実装する。

以下、実装。以前紹介した時とほぼ同じ。大きく違うのは Hotkey クラスを使うところ。
Hotkey.m

まずセッターとゲッター
- (Hotkey*)hotkey
{
return _hotkey;
}

- (void)setHotkey:(Hotkey*)hotkey
{
[hotkey retain];
[_hotkey release];
_hotkey = hotkey;
[self redraw];
}


再描画は - [Hotkey string] で得た文字列を使う。
- (void)redraw
{
[self setString:[_hotkey string]];
}


イベント系:ダブルクリック検出
- (void)mouseDown:(id)theEvent
{
if ([theEvent clickCount] >= 2) {
[self startEdit];
}
}

startEdit でキー入力モードへ移行する。

- (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;
}


_is_editing フラグで入力モードを管理している。キー入力を受け付けるモードになったら、現在のキー文字列を選択状態(反転表示)にする。


イベント処理:キー入力
- (void)keyDown:(NSEvent *)theEvent
{
if (!_is_editing) {
return;
}

UInt32 modifier = 0;
UInt32 keycode = [theEvent keyCode];

NSUInteger modifier_flags = [theEvent modifierFlags];
if (modifier_flags & NSShiftKeyMask) {
modifier |= shiftKey;
}
if (modifier_flags & NSCommandKeyMask) {
modifier |= cmdKey;
}
if (modifier_flags & NSAlternateKeyMask) {
modifier |= optionKey;
}
if (modifier_flags & NSControlKeyMask) {
modifier |= controlKey;
}

if (!([Hotkey isHotKeyForModifier:modifier])) {
if (keycode == kVK_Escape) {
[self redraw];
[self endEdit];
}
// abort
return;
}

if (![Hotkey isHotKeyForKeyCode:keycode]) {
// abort
return;
}

_hotkey.modifier = modifier;
_hotkey.code = keycode;

[self redraw];
[self endEdit];
}

最初に修飾キーを判定し、その後ホットキーとして受け付けるかどうかのチェックを入れる。それらのチェックが済んだら Hotkeyインスタンスへmodifierとcodeを設定し再描画させる。最後に endEdit を呼んで入力モードを終了する。

ホットキーとして登録できるのはCommand/Option/Controlerのいづれかの修飾キーが押されている場合のみで、そのルールは Hotkey クラスに用意しておく。
Hotkey.m
+ (BOOL)isHotKeyForModifier:(UInt32)modifier
{
if (modifier & (cmdKey | optionKey | controlKey)) {
return YES;
} else {
return NO;
}
}




HotkeyTextViewクラスが実装できたので、これを試すサンプル画面を作ってみる。
InterfaceBuilderで HotkeyTextView を2つ貼付けてみた。


AppControllerでアウトレットを設定し、これらへ Hotkeyを指定する。
AppController.m
- (void)awakeFromNib
{
_hotkey_register = [HotkeyRegister sharedRegister];

Hotkey *hotkey;

hotkey = [[[Hotkey alloc] init] autorelease];
hotkey.code = 0x23; // 'S'
hotkey.modifier = cmdKey | optionKey;
hotkey.target = self;
hotkey.action = @selector(keyDown:);
[_hotkey_register registHotkey:hotkey];
[_text1 setHotkey:hotkey];

hotkey = [[[Hotkey alloc] init] autorelease];
hotkey.code = 0x25; // 'L'
hotkey.modifier = cmdKey | optionKey;
hotkey.target = self;
hotkey.action = @selector(keyDown:);
[_hotkey_register registHotkey:hotkey];
[_text2 setHotkey:hotkey];

}


これでできあがり。動かしてみよう。
まず初期表示。


よし、問題なし。


次にダブルクリックして変更してみる。


大丈夫だ。

とりあえずいいようだ。

サンプル:HotKey-3.zip

- - - -
今回はホットキーを変更しても表示が変わるだけでシステムへの再登録は行っていない。
この辺りは次回以降。