2011年4月19日火曜日

Cocoa なんちゃってtabbed interface(3)

なんちゃってtabbedインターフェイス、本日はここまで作った。


まだ見た目を整えている段階。今日は「tabがたくさん増えたらtabの幅を調整する」部分を実装した。ウィンドウの大きさを変えたら


tabの幅も自動的に広がる、と。
あとはtab中の文字描画のtruncateだなあ。全角文字もありえるから果たして自分にできるかしらん。

いちおう現在のところのクラス構成はこうなっている。


MyCellクラスがtabの描画そのもの。だからtruncateもこのクラスの仕事になる。
TabViewはMyCellをMutableArrayで保持しており、tabの大きさと位置をきめている。現在アクティブなtabを記録するのもこのクラス。
PanelViewは単に「アクティブなtabと同じ色にぬられた」というだけのView。あとあとこのViewにファイルマネージャーもどきの実際のViewを置いていくことになる計画。
MyCellの描画コード。

-(void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView{
    [NSGraphicsContext saveGraphicsState];
    [controlView lockFocus];
    NSBezierPath* path=[NSBezierPath bezierPathWithRoundedRect:cellFrame xRadius:3 yRadius:3];
   
    [[NSColor blackColor] set];
    [path stroke];
    if(active){
       
        [[NSColor colorWithDeviceWhite:0.84 alpha:1.0]set]; 

    }
    else{
         [[NSColor windowFrameColor] set];
    }
        
    [path fill];
     
    NSSize size=[title sizeWithAttributes:stringAttrbutes];
    NSPoint point=NSMakePoint(((cellFrame.size.width-size.width)/2)+cellFrame.origin.x, (cellFrame.size.height-size.height) /2);
    [title drawAtPoint:point withAttributes:stringAttrbutes];
    drawedFrame=cellFrame;
    [controlView unlockFocus];
    [NSGraphicsContext restoreGraphicsState];
}
- (id)initWithTitle:(NSString *)aTitle{
    self=[super init];
    if(self){
        title=aTitle;
        active=NO;
        
        stringAttrbutes=[[NSMutableDictionary dictionary]retain];
        [stringAttrbutes setObject:[NSColor blackColor]
                              forKey:NSForegroundColorAttributeName];
  [stringAttrbutes setObject:[NSFont systemFontOfSize:13.0]
                              forKey: NSFontAttributeName];     
    }
    return self;
}

文字描画のアトリビュートが大半でありますな。

TabViewの描画部分。
-(CGFloat)calcTabWidth{
    CGFloat width=MAX_TAB_WIDTH;
    CGFloat frameWidth=[self bounds].size.width;
    if(FIRST_TAB_MARGIN+(width*[tabs count])+LAST_TAB_MARGIN>frameWidth){
        width=(frameWidth- FIRST_TAB_MARGIN-LAST_TAB_MARGIN)/[tabs count];
    }
    return width;
}
- (void)drawRect:(NSRect)dirtyRect
{
    // Drawing code here.
   
    NSBezierPath* path = [NSBezierPath bezierPathWithRect:[self bounds]];
 CGFloat closeButtonX;
  [[NSColor colorWithDeviceWhite:0.7 alpha:1.0]set]; 
 [path fill];
       
    if([tabs count]>0){
        CGFloat tabWidth=[self calcTabWidth];
        for(NSInteger i=0;i<[tabs count];i++){
            MyCell* cell=[tabs objectAtIndex:i];
            if(i==activeTabIndex) cell.active=YES;
            
            [cell drawWithFrame:NSMakeRect(FIRST_TAB_MARGIN+(i*tabWidth), 0, tabWidth, TAB_HEIGHT) inView:self];
            closeButtonX=FIRST_TAB_MARGIN+((i+1)*tabWidth);
        }
        
    }
    
  
    [closeButtonImage drawAtPoint:NSMakePoint(closeButtonX+10, 3) fromRect:NSZeroRect operation: NSCompositeSourceOver fraction:0.6];
    
}
-(NSInteger)cellAtPoint:(NSPoint)point{
    //NSLog(@"%lu",[tabs count]);
    MyCell* cell;
    for(NSUInteger i=0;i<[tabs count];i++){
        cell=[tabs objectAtIndex:i];
        NSRect rect=[cell drawedFrame];
        if(NSPointInRect(point, rect)){
            return i;
        }
    }
    return -1;
}
-(void)mouseDown:(NSEvent *)theEvent{
    NSPoint point = [self convertPointFromBase:[theEvent locationInWindow]];
 NSInteger index = [self cellAtPoint:point];
    if(index!=-1 && index!=activeTabIndex){
        MyCell* cell=[tabs objectAtIndex:activeTabIndex];
        cell.active=NO;
        cell=[tabs objectAtIndex:index];
        cell.active=YES;
        activeTabIndex=index;
        [self setNeedsDisplay:YES];
    }
}

新しいtabを開くためのボタンはまだdrawAtPointしているだけなので、これの処理が今後の課題。CellにViewなんか載せたくないしなあ。TabView側で「tabをくわえる」ボタンや「tabを閉じるボタン」のTrakingAreaとかも全部処理するしかないかな、というところ。

0 件のコメント:

コメントを投稿