ページ

2008年8月9日土曜日

SimpleCap (38) 範囲選択:Shiftキーによる平行移動

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

範囲選択で平行移動ができると便利だ。エクセルなどでは Shiftキーを押しながら図形を移動するとX軸、またはY軸方向のどちらかに沿っての平行移動が可能になる。



範囲選択(RubberBand)の移動個所に手を入れてみた。
SelectionHandler.m

NSPoint p_cp = cp; 
int constrain_mode = 0;
while ([theEvent type] != NSLeftMouseUp) {
theEvent = [window nextEventMatchingMask:(NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
cp = [view convertPoint:[theEvent locationInWindow] fromView:nil];
BOOL is_shiftkey = ([theEvent modifierFlags] & NSShiftKeyMask) ? YES : NO;

// constrain rule (1)
if (is_shiftkey) {
CGFloat dcpx = fabs(cp.x - p_cp.x);
CGFloat dcpy = fabs(cp.y - p_cp.y);
if (constrain_mode == 0) {
constrain_mode = (dcpx > dcpy) ? 1 : 2;
} else {
if (dcpx == 0 && dcpy > 5.0) {
constrain_mode =2;
} else if (dcpx > 5.0 && dcpy == 0) {
constrain_mode =1;
}
}
switch (constrain_mode) {
case 1: // horizontal moving
_rect.origin.x = cp.x + dx;
break;
case 2: // vertical moving
_rect.origin.y = cp.y + dy;
break;
default:
break;
}
} else {
_rect.origin.x = cp.x + dx;
_rect.origin.y = cp.y + dy;
}
  :
  :
p_cp = cp;
}


イベントループを形成(while)し、マウスのドラッグに合わせて RubberBandの位置を調整している。Shiftキーが押された場合には constrain_modeを設定し、水平方向または垂直方向のみに移動を強制するようにしている(switch文の個所)。

ただエクセルでもそうだが、例えば垂直方向に移動している途中で、左右に少し大きな移動を行なうと水平方向の平行移動に切り替わる。これは便利なので SimpleCap でもまねする。上記コードで下記の個所がモードきりかえの部分。
 if (constrain_mode == 0) {
constrain_mode = (dcpx > dcpy) ? 1 : 2;
} else {
if (dcpx == 0 && dcpy > 5.0) {
constrain_mode =2;
} else if (dcpx > 5.0 && dcpy == 0) {
constrain_mode =1;
}
}


最初の ==0 は初期処理。その後の if分が途中でのモード切り替え。例えば、水平方向の移動量が0(dcpx==0)で、垂直方向の移動量が5.0以上(dcpy > 5.0)なら、移動モードを垂直方向に切り替える。 "5.0" は実際に試してみて感覚的に決めた数値。