モデルができたのでいよいよ表示にとりかかる。なお修正を加えるクラスは SelectionHandler と呼ぶ範囲選択を処理するクラス。GoFでいう Commandパターン辺りに該当するのだろうか。
interface SelectionHandler : HandlerBaseHandlerBase は NSObject の派生クラス(なので NSView 系統ではない)。{ NSRect _rect; : }
Selection History Expose表示ボタン
まずは範囲選択にボタンを追加する。自作のボタンバークラスへボタンの追加処理を加える。
実行するとこんな感じ。アイコンは後でちゃんと作る。
[参考情報] cocoaの日々 ThinButton - Google 検索
仮表示
まずはとりあえず履歴領域を白く塗りつぶしてみよう。
- (void)drawRect:(NSRect)rect { : case STATE_HISTORY: [self drawBackground:rect]; [self drawAllHistorySelection]; break; :先程のボタンが押されたら半透明の黒で塗りつぶし(drawBackgroud)、その後履歴の描画にとりかかる(drawAllHistorySelection)。
履歴の描画に加えて現在表示中の領域も表示するようにした。こうすると履歴がひとつもない場合でも最低は1つ表示されるので特別な処理(履歴表示を禁じるとかメッセージを出すとか)が不要になる。
- (void)drawAllHistorySelections { NSLog(@"TODO: %s", __PRETTY_FUNCTION__); // [1] draw current selection [self drawHistorySelection:_rect]; // [2] draw history selection for (NSValue* historyValue in [[SelectionHistory sharedSelectionHistory] array]) { [self drawHistorySelection:[historyValue rectValue]]; } }仮描画のコード。白く塗りつぶすだけ。
- (void)drawHistorySelection:(NSRect)rect { [[NSColor whiteColor] set]; NSRectFill(rect); }
さて実行してみよう。
出た。
履歴選択
白い部分をクリックした時にその履歴の領域(位置+サイズ)を採用するように修正する。まずはクリック判定用のメソッドを書く。
- (NSRect)rectOfhistorySelectionsAt:(NSPoint)cp { NSRect rect = NSZeroRect; for (NSValue* historyValue in [[SelectionHistory sharedSelectionHistory] array]) { NSRect historyRect = [historyValue rectValue]; if (NSPointInRect(cp, historyRect)) { rect = historyRect; break; } } return rect; }戻り値にクリックされた領域を返す。該当領域がない場合は NSZeroRect が返る。
これを使って mouseDown: を実装する。
- (void)mouseDown:(NSEvent *)theEvent { : case STATE_HISTORY: historyRect = [self rectOfhistorySelectionsAt:cp]; if (!NSIsEmptyRect(historyRect)) { [self setFrame:historyRect]; } [self changeState:STATE_RUBBERBAND]; return; // ** not reached ** :白い部分がクリックされた場合は現在の範囲選択の位置とサイズを変更した後、元の範囲選択画面へ戻る。それ以外をクリックした場合は何もせずに戻る。
位置とサイズの変更はアンドゥ対象となるため setFrame: メソッドを用意し、そこで必要な手当を行っておく。
-(void)setFrame:(NSRect)frame { CaptureView* view = [_capture_controller view]; NSUndoManager* undoManager = [view undoManager]; [[undoManager prepareWithInvocationTarget:self] setRubberBandFrame:_rect]; [undoManager setActionName:NSLocalizedString(@"UndoResizeSelection", @"")]; [self setRubberBandFrame:frame]; }
実行結果
初期状態
履歴を表示し適当な領域を選択すると...
出た。アンドゥもちゃんと働く。って静止画じゃわかりずらいが..
考察
履歴の表示は重なったり小さくて見にくいケースが想定されるので工夫が必要。また(200x200のような)サイズ表示があるとよさそうだ。それと選択された時に点滅するとか何らかのアニメーションを起こしてユーザにフィードバックすることも必要だな。
- - - -
次回も引き続き表示。
Responses
Leave a Response