2

NSTableViews/NSOutlineViewsにいくつかの特定の動作を実装することについて質問があります。

私が達成しようとしていること:

Photoshopのレイヤーパネルの動作を模倣するNSOutlineViewを作成しようとしています([レイヤー]列が階層的であることを除く)。私のアウトラインビューは、「レイヤー」列、「可視性」列、および「ロック」列を持つ3列のテーブルです。「visibility」列と「lock」列をNSImageCellsとして実装し、「layer」列をカスタムテキストと画像セルとして実装しました。

具体的には、実装に苦労している動作は次のとおりです。

  • Photoshopと同様に、ユーザーは可視性(眼球)アイコンをクリックして別の行に上下にドラッグし、クリックした最初の行の可視性に応じて他の行の可視性を「オン」または「オフ」にすることができます。 .Photoshopがレイヤーの表示と非表示をどのように行うかを正確に示します。テーブルに多くの行がある場合は、自動スクロールをサポートする必要があることに注意してください。

  • Photoshopと同様に、[レイヤー]列の1つ以上の行が選択されている場合、表示/ロック列の後ろにハイライトバーを配置しないでください(つまり、行のハイライトが列を通過しないようにする必要があります)。

  • 「visibility」または「lock」列をクリックおよび/またはドラッグしても、テーブルの選択は変更されません...上記の状態のみが変更されます。

私はこれを機能させるために1週間壁に頭をぶつけてきました。Controls&Cellsプログラミングガイド、テーブルビュープログラミングガイド、NSCell、NSActionCell、NSTableView、NSControl、NSOutlineViewのクラスリファレンス、NSOutlineViewDelegateとNSOutlineViewDataSourceのプロトコルリファレンスを読み、1週間を通してさまざまなアプローチを試してきました。 。そして私はこれを理解していません。

誰かが私を正しい方向に導くことができますか?助けてくれてありがとう!

4

1 に答える 1

2

いくつかの追加のWeb検索と実験を通して、私は自分の質問のほとんどに答えることができます。

NSOUTLINEVIEWの最初の列のみを強調表示する

NSOutlineViewをサブクラス化して実装することにより、最初の列の選択された行にのみ選択のハイライトを表示させることができました。

- (void)highlightSelectionInClipRect:(NSRect)clipRect
{
    NSRange visibleRowIndexes = [self rowsInRect:clipRect];
    NSIndexSet *selectedRowIndexes = [self selectedRowIndexes];

    NSInteger currentRow = visibleRowIndexes.location;
    NSInteger lastRow = currentRow + visibleRowIndexes.length;

    NSColor *highlightColor;

    //Determine color of selection bar based on key/main/first responder status.
    if (self == [[self window] firstResponder] && [[self window] isMainWindow] && [[self window] isKeyWindow]) {
        highlightColor = [NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.3 alpha:1.0];
    } else
        highlightColor = [NSColor lightGrayColor];
    }
    [highlightColor setFill];

    //Get the Rect of only the name column. This is the only column that will be highlighted.
    //We'll intersect this rect with the row rect for the area to fill in.
    NSInteger nameColumn = [self columnWithIdentifier:@"name"];
    NSRect nameColumnRect = [self rectOfColumn:nameColumn];

    while (currentRow < lastRow) {
        if ([selectedRowIndexes containsIndex:currentRow]) {
            NSRect drawRect = NSIntersectionRect([self rectOfRow:currentRow], nameColumnRect);
            NSRectFill(drawRect);
        }
        currentRow++;
    }
}

次のように、カスタムNSCellサブクラスのdrawInteriorWithFrame:inView:メソッドをオーバーライドして、標準のハイライトが描画されないようにする必要があることに注意してください。

-(void) drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    //do drawing here...don't call super.
}

したがって、質問の一部に対する解決策があります。これが「正しい」方法でない場合は、私に知らせてください:)。

VIS / LOCK列のクリック/ドラッグは、選択を変更 しないでください。

-(NSIndexSet *) outlineView:(NSOutlineView *)outlineView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes

方法。可視性またはロック列で発生したドラッグの途中にいる場合は、現在のselectedRowsを返すだけで、選択を同じに保つことができます。私はまだこれを実装していませんが、最終的な問題が解決されれば簡単になるはずです(以下を参照)。

状態を変更するために可視性/ロックされた列を上下にドラッグする

私はこれに本当に近づいています。カスタムNSCellでは、次の3つのメソッドをオーバーライドしました。

-(BOOL) startTrackingAt:(NSPoint)startPoint inView:(NSView *)controlView
-(BOOL) continueTracking:(NSPoint)lastPoint at:(NSPoint)currentPoint inView:(NSView *)controlView
-(void) stopTracking:(NSPoint) lastPoint at:(NSPoint)stopPoint inView:(NSView *)controlView mouseIsUp:(BOOL)flag

私は私の最後の問題に取り掛かっています、そしてここにそれがあります:私はいつドラッグ操作の中にいるのか、そしていつドラッグ操作が終了するのかを知る必要があります。これを行うには2つの方法があります。

オーバーライドしない場合

+(BOOL) prefersTrackingUntilMouseUp

NSCellサブクラスで(デフォルトのNO値を返すため)、セルを離れてドラッグ操作中に次のセルに移動するたびに、stopTracking:at:inView:mouseIsUp:メッセージを受け取ります...つまり、そのメソッドを使用して、ドラッグ操作がいつ実行されるかを判別しないでください。

代わりに私オーバーライドする場合

+(BOOL) prefersTrackingUntilMouseUp

YESを返すと、stopTrackingが表示されます:...マウスを上に向けた場合にのみ呼び出します。これはすばらしいことです...しかし、問題は、テーブルがmouseDownまたはドラッグ中にセルのUIを更新していないように見えることです。セル内。たとえば、startTracking:...メソッドで、セルのobjectValueをnilに設定すると(その画像が表示されなくなるように)、マウスボタンが上に戻るか、カーソルが細胞。(prefersTrackingUntilMouseUpがNOを返した場合、すぐに更新されます)。

したがって、セルのUIをすぐに(mouseDownで)更新できるだけでなく、ドラッグ操作がいつ完了したかを知る方法も必要です。これがパズルの最後のピースです。誰か助けてもらえますか?

于 2012-06-03T19:31:08.320 に答える