home link download back number special issue

HMDT - Special Issue / Sketch BP / Sketch に見るドローオブジェクトの作成


- Case Study -

Sketch に見るドローオブジェクトの作成

ドローオブジェクトを作る

次はドローオブジェクトを作ることを考えてみよう。Sketch では、基本的にマウスをドラッグして作ることになってるんだ。Sketch の場合、必要な情報は、ドローオブジェクトの大きさ(境界)だけなんだ。作成の流れは、

  • ドローオブジェクトクラスのインスタンスを作る
  • ドラッグのトラッキングルーチンに入る
  • ドラッグされたら、ドローオブジェクトの大きさを変える
  • ドラッグが終了したらおしまい

って感じだ。


Sketch に見るドローオブジェクトの作成

じゃ、コードの中に入っていくぞ。スタートポイントは、SKTGraphicView の mouseDown: になる。ユーザが View をクリックすることによって始まるんだ。

mouseDown:

mouseDown: からスタートする処理はいっぱいあるけど、オブジェクト作成の場合は createGraphicOfClass:withEvent: を呼び出すことになる。

Sketch/SKTGraphicView.m
- (void)mouseDown:(NSEvent *)theEvent {
    Class theClass = [[SKTToolPaletteController sharedToolPaletteController] currentGraphicClass];

    ...

    if (theClass) {
        [self clearSelection];
        [self createGraphicOfClass:theClass withEvent:theEvent];
    } else {
    
    ...
}

まず SKTToolPaletteController に問い合わせて、いま選択しているツールを取得するんだ。もしなにか選択されてるなら(nil じゃなかったら)、createGraphicOfClass:withEvent: に移る。


createGraphicOfClass:withEvent:

ここでは、ドローオブジェクトである SKTGraphic のインスタンスが作られるんだ。

Sketch/SKTGraphicView.m
- (void)createGraphicOfClass:(Class)theClass 
                     withEvent:(NSEvent *)theEvent {
    SKTDrawDocument *document = [self drawDocument];
    _creatingGraphic = [[theClass allocWithZone:[document zone]] init];
    if ([_creatingGraphic createWithEvent:theEvent inView:self]) {
        [document insertGraphic:_creatingGraphic atIndex:0];
        [self selectGraphic:_creatingGraphic];
        if ([_creatingGraphic isEditable]) {
            [self startEditingGraphic:_creatingGraphic withEvent:nil ];
        }

        ...

    }
    [_creatingGraphic release];
    _creatingGraphic = nil;
}

SKTGraphic のインスタンスが作られて、_creatingGraphic っていうインスタンス変数に入れられる。そして、SKTGraphic の createWithEvent:inView: っていうメソッドに入るんだ。こいつが主役だぜ!

それが終わると、ドローオブジェクトができあがったことになる。あとはドキュメントに追加したり、後処理をして、おしまい。


次は SKTGraphic の中に入るぜ。いまのところ createWithEvent:inView: を実装しているのは、ドローオブジェクトのルートクラスである SKTGraphic だけだ。だけど、将来拡張するならば、各ドローオブジェクトごとに createWithEvent:inView: を継承することが考えられるね。

createWithEvent:inView:

ドローオブジェクトを作るためのメソッドだ。メインの目的は、作られるオブジェクトの大きさを決定すること。

Sketch/DocumentMode.subproj/SKTGraphic.m
- (BOOL)createWithEvent:(NSEvent *)theEvent 
                  inView:(SKTGraphicView *)view {
    ...

    while (1) {
        theEvent = [[view window] 
            nextEventMatchingMask:
              (NSLeftMouseDraggedMask | NSLeftMouseUpMask)];
        point = [view convertPoint:[theEvent locationInWindow] fromView:nil];
        if (snapsToGrid) {
            point.x = floor((point.x / spacing) + 0.5) * spacing;
            point.y = floor((point.y / spacing) + 0.5) * spacing;
        }
        [view setNeedsDisplayInRect:[self drawingBounds]];
        knob = [self resizeByMovingKnob:knob toPoint:point];
        [view setNeedsDisplayInRect:[self drawingBounds]];
        if (echoToRulers) {
            [view continueEchoingMoveToRulers:[self bounds]];
        }
        if ([theEvent type] == NSLeftMouseUp) {
            break;
        }
    }

    ...

}

while ループを回している。その中で nextEventMatchingMask: を使って、ユーザからのイベント待ち状態にしているんだ。マウスがドラッグされるか、ボタンが離されるまで、ここでブロックされるので注意。マウスが動いたら、マウスの現在の座標を調べる。そして resizeByMovingKnob:toPoint: を呼び出すんだ。これが実際にオブジェクトの大きさを変えるためのメソッドだ。これについては、「ドローオブジェクトを編集する」で調べよう。

あとは、マウスボタンが離されたら、このループを抜ける処理があって、それで完了。


Home | Link | Download | Back Number | Speciall Issue

Sketch BP

mailto: mkino@xd5.so-net.ne.jp

HMDT