目標
xcodeのパレットみたいなものを作りたい。
画面上部にある4つのアイコンはボタンで、下段の表示を切り替えるタブの役割。アイコンが並んでいる横長の白い四角の領域は NSSplitViewの dividerで、ドラッグして上下させることができる。
これをどんな風に作ったらいいだろう、という記録。
作業
NSSplitViewそのものにボタンを乗せるアプローチがうまくいかなかったので、ボタンを載せたカスタムビューを別途用意して、それを NSSplittViewのスーパービューに配置し、ちょうど dividerの上に来るように配置する戦略を取ってみた。これで合ってるかどうかはなんとも言えない。
まず http://stackoverflow.com/questions/11593541/how-to-add-buttons-to-a-nssplitter-handle を参考に
- NSSplitterのサブクラス MySplitViewを作る
- インターフェースビルダで NSSplitViewを配置、Custom Classを MySplitViewにする
- NSWindowの外に Custom Viewを配置。 その上にボタンセルの NSMatrixを置く。NSMatrixは MySplitViewにアウトレットを用意してつないでおく。
つぎに MySplitViewのメソッドを上書きする。
awakeFromNibでボタンの乗ったカスタムビューをスーパービューに追加する。 ※ この辺あんまり綺麗じゃない気がしている。
drawDividerInRect:, dividerThicknessで dividerの大きさを決めて描画する。描画時に updateToolbarPositionを呼んでボタンの置かれたCustom Viewの位置を更新。
※ adjustSubviewsはこの例では使われていない。
-(void)awakeFromNib {
[self.superview addSubview:self.buttonMatrixView];
}
-(void)drawDividerInRect:(NSRect)rect
{
[[NSColor grayColor] set];
NSRectFill(rect);
[self updateToolbarPosition];
}
-(CGFloat)dividerThickness
{
return 20.0; // ツールバーの高さ + 上下マージン
}
-(void)adjustSubviews
{
[super adjustSubviews];
[self updateToolbarPosition];
}
-(void)updateToolbarPosition
{
NSRect frame;
frame.origin.x = (self.frame.size.width - self.buttonMatrixView.bounds.size.width)/2;
frame.origin.y = self.bounds.size.height - [self positionOfDividerAtIndex:0];
frame.size = self.buttonMatrixView.bounds.size;
[self.buttonMatrixView setFrame:frame];
}
// ref. https://github.com/malcommac/NSSplitView-Animatable
- (CGFloat)positionOfDividerAtIndex:(NSInteger)dividerIndex
{
while (dividerIndex >= 0 && [self isSubviewCollapsed:[[self subviews] objectAtIndex:dividerIndex]])
dividerIndex--;
if (dividerIndex < 0)
return 0.0f;
NSRect priorViewFrame = [[[self subviews] objectAtIndex:dividerIndex] frame];
return [self isVertical] ? NSMaxX(priorViewFrame) : NSMaxY(priorViewFrame);
}
カーソルの形状やcollapse対応などはしていないのでここままでは不十分だけど、それっぽいものは大体作れたと思う。
参考
- stackoverflow: How to add buttons to a NSSplitter handle?
- GitHub: NSSplitView-Animatable