画面分割その1

昔から作ろうとしていて、挫折していた画面分割のUIを作ることにした。

以前は、汎用性を考慮した設計にしようと努力して失敗したので、今回は努力しない方針とする。

まずは、NSScrollerにボタンをつける。

../../../_images/split1.png

垂直スクロールバーの上の方にある。2つのアイコンがそれ。

コードはこんな感じ。

TDScrollView.h

@interface TDScrollView : NSScrollView
@end

TDScrollView.m

#import "TDScrollView.h"

@interface TDScrollView ()

@property (strong) NSButton* vSplitOpenButton;
@property (strong) NSButton* vSplitCloseButton;

@end


@implementation TDScrollView


- (IBAction) responseOpenSplit:(id)sender
{
    id theObject = [NSApp targetForAction:@selector(openSplit:)
                                       to:self
                                     from:self];
    if(theObject && theObject != self)
    {
        [NSApp sendAction:@selector(openSplit:) to:theObject from:self];
    }
}

- (IBAction) responseCloseSplit:(id)sender
{
    id theObject = [NSApp targetForAction:@selector(closeSplit:)
                                       to:self
                                     from:self];
    if(theObject && theObject != self)
    {
        [NSApp sendAction:@selector(closeSplit:) to:theObject from:self];
    }
}

- (void)tile
{
    [super tile];

    if(  self.hasVerticalScroller)
    {
        NSScroller* vScroller        = self.verticalScroller;
        NSRect      vScrollerFrame   = vScroller.frame;

        // 分割ボタン
        if( !self.vSplitOpenButton )
        {
            self.vSplitOpenButton = [[NSButton alloc] initWithFrame: NSZeroRect];
            self.vSplitOpenButton.buttonType = NSMomentaryLightButton;
            self.vSplitOpenButton.bezelStyle = NSThickSquareBezelStyle;
            self.vSplitOpenButton.bordered = NO;
            self.vSplitOpenButton.image = [NSImage imageNamed: @"splitopen"];
            self.vSplitOpenButton.imagePosition = NSImageOnly;
            [self.vSplitOpenButton.cell setImageScaling:NSImageScaleProportionallyDown];

            self.vSplitOpenButton.target = self;
            self.vSplitOpenButton.action = @selector(responseOpenSplit:);

            [self addSubview:self.vSplitOpenButton];
        }

        NSButton*   vOpenButton      = self.vSplitOpenButton;
        NSRect      vOpenButtonFrame;

        // 分割ボタンの位置を設定
        vOpenButtonFrame.origin.x = vScrollerFrame.origin.x;
        vOpenButtonFrame.origin.y = vScrollerFrame.origin.y;
        vOpenButtonFrame.size.height = vScrollerFrame.size.width;
        vOpenButtonFrame.size.width  = vScrollerFrame.size.width;
        vOpenButton.frame = vOpenButtonFrame;

        // スクローラーの表示非表示を同期する
        vOpenButton.hidden = vScroller.hidden;

        // 結合ボタン
        if( !self.vSplitCloseButton )
        {
            self.vSplitCloseButton = [[NSButton alloc] initWithFrame: NSZeroRect];
            self.vSplitCloseButton.buttonType = NSMomentaryLightButton;
            self.vSplitCloseButton.bezelStyle = NSThickSquareBezelStyle;
            self.vSplitCloseButton.bordered = NO;
            self.vSplitCloseButton.image = [NSImage imageNamed: @"splitclose"];
            self.vSplitCloseButton.imagePosition = NSImageOnly;
            [self.vSplitCloseButton.cell setImageScaling:NSImageScaleProportionallyDown];

            self.vSplitCloseButton.target = self;
            self.vSplitCloseButton.action = @selector(responseCloseSplit:);

            [self addSubview:self.vSplitCloseButton];
        }

        NSButton*   vCloseButton      = self.vSplitCloseButton;
        NSRect      vCloseButtonFrame;

        // 結合ボタンの位置を設定
        vCloseButtonFrame.origin.x = vScrollerFrame.origin.x;
        vCloseButtonFrame.origin.y = vScrollerFrame.origin.y + vOpenButtonFrame.size.height;
        vCloseButtonFrame.size.height = vScrollerFrame.size.width;
        vCloseButtonFrame.size.width  = vScrollerFrame.size.width;
        vCloseButton.frame = vCloseButtonFrame;

        // スクローラーの表示非表示を同期する
        vCloseButton.hidden = vScroller.hidden;

        // スクロールバーの大きさをボタンに合わせて調整
        vScrollerFrame.origin.y += vOpenButtonFrame.size.height + vCloseButtonFrame.size.height;
        vScrollerFrame.size.height -= vOpenButtonFrame.size.height + vCloseButtonFrame.size.height;
        [vScroller setFrame:vScrollerFrame];
    }

}

@end

tileメソッドをオーバーライドしないと実装できない。 IBでなんとかしようとしたり、サブクラスしないでなんんとかできると考えてはいけない。