|
HMDT - Special Issue / Sketch BP / Sketch に見るドローオブジェクトの編集 |
- Case Study -
Sketch に見るドローオブジェクトの編集
|
|
Sketch/DocumentMode.subproj/SKTGraphic.h
|
- (BOOL)isEditable; |
これを呼ぶことで、SKTGraphicView は、そのドローオブジェクトが編集モードに入れるかどうかを、知ることができるんだ。デフォルトでは NO を返すように実装されている。SKTTextArea は YES を返しているぜ。
編集モードに入るには、まず startEditingWithEvent:inView: を呼ぶ。これでドローオブジェクトが編集モードになる。そこから抜けるには、endEditingInView: を呼ぶんだ。
Sketch/DocumentMode.subproj/SKTGraphic.h - (void)startEditingWithEvent:(NSEvent *)event inView:(SKTGraphicView *)view; - (void)endEditingInView:(SKTGraphicView *)view;
この 2 つのメソッドを実装するのが、編集対応のメインだ。
Skethc でのドローオブジェクトの編集を調べるには、
の 2 つを調べることになる。ここでは、編集モードへの入り方、抜け方を見てみよう。対象となるのは SKTGraphicView クラスだ。
もちろん、スタートポイントは mouseDown: だ。今回は、ダブルクリックの処理に注目することになる。
Sketch/SKTGraphicView.m- (void)mouseDown:(NSEvent *)theEvent { Class theClass = [[SKTToolPaletteController sharedToolPaletteController] currentGraphicClass]; if ([self editingGraphic]) { [self endEditing]; } if ([theEvent clickCount] > 1) { NSPoint curPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; SKTGraphic *graphic = [self graphicUnderPoint:curPoint]; if (graphic && [graphic isEditable]) { [self startEditingGraphic:graphic withEvent:theEvent]; return; } } ... }
NSEvent の clickCount を調べることで、ダブルクリックと分かる。ダブルクリックで、
編集モードに入るために、startEditingGraphic:withEvent: を呼び出すんだ。
このメソッドは簡単。SKTGraphic の startEditingWithEvent:inView: を呼び出すだけだ。
Sketch/SKTGraphicView.m- (void)startEditingGraphic:(SKTGraphic *)graphic withEvent:(NSEvent *)event { [graphic startEditingWithEvent:event inView:self]; }
これで編集モード突入!
そして編集モードから抜けるための endEditing: メソッド。これも mouseDown: から呼び出される。
Sketch/SKTGraphicView.m- (void)endEditing { if (_editingGraphic) { [_editingGraphic endEditingInView:self]; _editingGraphic = nil; _editorView = nil; } }
現在編集中のドローオブジェクトの endEditingInView: を呼び出してやる。これで編集モードから、通常モードに戻ってくるんだ。
んじゃ、続いて SKTTextArea によるテキストオブジェクト編集の様子を。SKTTextArea は SKTGraphic を継承したクラスで、テキストオブジェクトを取り扱うんだ。テキストの編集には NSTextView を使う。その NSTextView は、Interface Builder であらかじめ作られるんじゃなくて、コード上で on the fly で作られる。それをやるのが newEditor() だ。
新しい NSTextView を作るための関数だ。
Sketch/DocumentMode.subproj/SKTTextArea.mstatic NSTextView *newEditor() { NSLayoutManager *lm = [[NSLayoutManager allocWithZone:NULL] init]; NSTextContainer *tc = [[NSTextContainer allocWithZone:NULL] initWithContainerSize:NSMakeSize(1.0e6, 1.0e6)]; NSTextView *tv = [[NSTextView allocWithZone:NULL] initWithFrame:NSMakeRect(0.0, 0.0, 100.0, 100.0) textContainer:nil]; [lm addTextContainer:tc]; [tc release]; [tv setTextContainerInset:NSMakeSize(0.0, 0.0)]; [tv setDrawsBackground:NO]; [tv setAllowsUndo:YES]; [tc setTextView:tv]; [tv release]; return tv; }
この中で NSLayoutManager、 NSTextContainer、NSTextView が作られているんだ。返り値は NSTextView へのポインタ。注意しないといけないのは、NSLayoutManager が release されていないこと。Ref count は 1 になっている。だから、使い終わったら、自分で release してやらないといけないんだ。
そして SKTTextArea を編集モードにするためのメソッド。ここでやることはたくさんあるぞ!
Sketch/DocumentMode.subproj/SKTTextArea.m- (void)startEditingWithEvent:(NSEvent *)event inView:(SKTGraphicView *)view { NSTextView *editor; NSTextStorage *contents = [self contents]; NSSize maxSize = [self maxSize]; NSSize minSize = [self minSize]; NSRect bounds = [self bounds]; if (!sharedEditorInUse) { if (!sharedEditor) { sharedEditor = newEditor(); } sharedEditorInUse = YES; editor = sharedEditor; } else { editor = newEditor(); } ... [contents addLayoutManager:[editor layoutManager]]; [view addSubview:editor]; [view setEditingGraphic:self editorView:editor]; [editor setSelectedRange:NSMakeRange(0, [contents length])]; [editor setDelegate:self]; // Make sure we redisplay [self didChange]; [[view window] makeFirstResponder:editor]; if (event) { [editor mouseDown:event]; } }
まず、newEditor() を使って、NSTextView を取り出す。そして、
と、これだけの処理をしてやることによって、NSTextView を使えるようになるのだ。こんなにやることがある、と言うべきか、これしかない、と言うべきか?
こっちは編集モードから抜けるときのメソッド。やることは、さっきの逆だね。
Sketch/DocumentMode.subproj/SKTTextArea.m- (void)endEditingInView:(SKTGraphicView *)view { if ([view editingGraphic] == self) { NSTextView *editor = (NSTextView *)[view editorView]; [editor setDelegate:nil]; [editor removeFromSuperview]; [[self contents] removeLayoutManager:[editor layoutManager]]; if (editor == sharedEditor) { sharedEditorInUse = NO; } else { [[editor layoutManager] release]; } [view setEditingGraphic:nil editorView:nil]; } }
順に追っていくと、
と、いうわけ。さっきときれに逆でしょ。これで後片付けが終わって、我々には、編集された NSTextStorage だけが残るんだ。
|
Home | Link | Download | Back Number | Speciall Issue
|