/*
HMTabItemView.m

Author: Makoto Kinoshita

Copyright 2004-2006 The Shiira Project. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted 
provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions 
  and the following disclaimer.

  2. Redistributions in binary form must reproduce the above copyright notice, this list of 
  conditions and the following disclaimer in the documentation and/or other materials provided 
  with the distribution.

THIS SOFTWARE IS PROVIDED BY THE SHIIRA PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE SHIIRA PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
POSSIBILITY OF SUCH DAMAGE.
*/

#import "HMAppKitEx.h"
#import "HMTabItemGroupView.h"
#import "HMTabItemView.h"
#import "HMTabView.h"
#import "HMTabViewItem.h"
#import "HMProgressIndicator.h"

static NSImage* _selectedLeftBottomImage = nil;
static NSImage* _selectedLeftMiddleImage = nil;
static NSImage* _selectedLeftTopImage = nil;
static NSImage* _selectedMiddleBottomImage = nil;
static NSImage* _selectedMiddleMiddleImage = nil;
static NSImage* _selectedMiddleTopImage = nil;
static NSImage* _selectedRightBottomImage = nil;
static NSImage* _selectedRightMiddleImage = nil;
static NSImage* _selectedRightTopImage = nil;

static NSImage* _selectedOutLeftBottomImage = nil;
static NSImage* _selectedOutLeftMiddleImage = nil;
static NSImage* _selectedOutLeftTopImage = nil;
static NSImage* _selectedOutMiddleBottomImage = nil;
static NSImage* _selectedOutMiddleMiddleImage = nil;
static NSImage* _selectedOutMiddleTopImage = nil;
static NSImage* _selectedOutRightBottomImage = nil;
static NSImage* _selectedOutRightMiddleImage = nil;
static NSImage* _selectedOutRightTopImage = nil;

static NSRect   _selectedLeftBottomRect = {{0, 0}, {0, 0}};
static NSRect   _selectedLeftMiddleRect = {{0, 0}, {0, 0}};
static NSRect   _selectedLeftTopRect = {{0, 0}, {0, 0}};
static NSRect   _selectedMiddleBottomRect = {{0, 0}, {0, 0}};
static NSRect   _selectedMiddleMiddleRect = {{0, 0}, {0, 0}};
static NSRect   _selectedMiddleTopRect = {{0, 0}, {0, 0}};
static NSRect   _selectedRightBottomRect = {{0, 0}, {0, 0}};
static NSRect   _selectedRightMiddleRect = {{0, 0}, {0, 0}};
static NSRect   _selectedRightTopRect = {{0, 0}, {0, 0}};

static NSImage* _tabBarLeftImage = nil;
static NSImage* _tabBarMiddleImage = nil;
static NSImage* _tabBarRightImage = nil;

static NSRect   _tabBarLeftRect = {{0, 0}, {0, 0}};
static NSRect   _tabBarMiddleRect = {{0, 0}, {0, 0}};
static NSRect   _tabBarRightRect = {{0, 0}, {0, 0}};

@implementation HMTabItemView

//--------------------------------------------------------------//
#pragma mark -- Initialize --
//--------------------------------------------------------------//

+ (void)load
{
    NSAutoreleasePool*  pool;
    pool = [[NSAutoreleasePool alloc] init];
    
    // Get resources
    if (!_selectedLeftBottomImage) {
        _selectedLeftBottomImage = [[NSImage imageNamed:@"tabSelectedLB"] retain];
        _selectedLeftMiddleImage = [[NSImage imageNamed:@"tabSelectedLM"] retain];
        _selectedLeftTopImage = [[NSImage imageNamed:@"tabSelectedLT"] retain];
        _selectedMiddleBottomImage = [[NSImage imageNamed:@"tabSelectedMB"] retain];
        _selectedMiddleMiddleImage = [[NSImage imageNamed:@"tabSelectedMM"] retain];
        _selectedMiddleTopImage = [[NSImage imageNamed:@"tabSelectedMT"] retain];
        _selectedRightBottomImage = [[NSImage imageNamed:@"tabSelectedRB"] retain];
        _selectedRightMiddleImage = [[NSImage imageNamed:@"tabSelectedRM"] retain];
        _selectedRightTopImage = [[NSImage imageNamed:@"tabSelectedRT"] retain];
        
        _selectedOutLeftBottomImage = [[NSImage imageNamed:@"tabSelectedOutLB"] retain];
        _selectedOutLeftMiddleImage = [[NSImage imageNamed:@"tabSelectedOutLM"] retain];
        _selectedOutLeftTopImage = [[NSImage imageNamed:@"tabSelectedOutLT"] retain];
        _selectedOutMiddleBottomImage = [[NSImage imageNamed:@"tabSelectedOutMB"] retain];
        _selectedOutMiddleMiddleImage = [[NSImage imageNamed:@"tabSelectedOutMM"] retain];
        _selectedOutMiddleTopImage = [[NSImage imageNamed:@"tabSelectedOutMT"] retain];
        _selectedOutRightBottomImage = [[NSImage imageNamed:@"tabSelectedOutRB"] retain];
        _selectedOutRightMiddleImage = [[NSImage imageNamed:@"tabSelectedOutRM"] retain];
        _selectedOutRightTopImage = [[NSImage imageNamed:@"tabSelectedOutRT"] retain];
        
        _selectedLeftBottomRect.size = [_selectedLeftBottomImage size];
        _selectedLeftMiddleRect.size = [_selectedLeftMiddleImage size];
        _selectedLeftTopRect.size = [_selectedLeftTopImage size];
        _selectedMiddleBottomRect.size = [_selectedMiddleBottomImage size];
        _selectedMiddleMiddleRect.size = [_selectedMiddleMiddleImage size];
        _selectedMiddleTopRect.size = [_selectedMiddleTopImage size];
        _selectedRightBottomRect.size = [_selectedRightBottomImage size];
        _selectedRightMiddleRect.size = [_selectedRightMiddleImage size];
        _selectedRightTopRect.size = [_selectedRightTopImage size];
        
        _tabBarLeftImage = [[NSImage imageNamed:@"tabBarSelectedL"] retain];
        _tabBarMiddleImage = [[NSImage imageNamed:@"tabBarSelectedM"] retain];
        _tabBarRightImage = [[NSImage imageNamed:@"tabBarSelectedR"] retain];
        
        _tabBarLeftRect.size = [_tabBarLeftImage size];
        _tabBarMiddleRect.size = [_tabBarMiddleImage size];
        _tabBarRightRect.size = [_tabBarRightImage size];
    }
    
    [pool release];
}

- (id)initWithFrame:(NSRect)frame tabViewItem:(HMTabViewItem*)tabViewItem
{
    self = [super initWithFrame:frame];
    if (!self) {
        return nil;
    }
    
    // Initialize instance variable
    _tabViewItem = tabViewItem;
    _thumbnailInterpolation = NSImageInterpolationHigh;
    
    // Create close button
    NSImage*    image;
    NSRect      rect;
    image = [NSImage imageNamed:@"tabClose"];
    rect.origin = NSZeroPoint;
    rect.size = [image size];
    _closeButton = [[NSButton alloc] initWithFrame:rect];
    [_closeButton setImage:image];
    [_closeButton setBezelStyle:NSRegularSquareBezelStyle];
    [_closeButton setButtonType:NSMomentaryChangeButton];
    [_closeButton setBordered:NO];
    [_closeButton setTarget:[[_tabViewItem tabView] delegate]];
    [_closeButton setAction:@selector(closeTabAction:)];
    [self addSubview:_closeButton];
    
    rect.origin = NSZeroPoint;
    rect.size = NSMakeSize(16.0f, 16.0f);
    _nsProgressIndicator = [[NSProgressIndicator alloc] initWithFrame:rect];
    [_nsProgressIndicator setControlSize:NSSmallControlSize];
    [_nsProgressIndicator setStyle:NSProgressIndicatorSpinningStyle];
    [_nsProgressIndicator setDisplayedWhenStopped:NO];
    [_nsProgressIndicator setMinValue:0.0f];
    [_nsProgressIndicator setMaxValue:1.0f];
    [_nsProgressIndicator sizeToFit];
    [self addSubview:_nsProgressIndicator];
    
    rect.origin = NSZeroPoint;
    rect.size = NSMakeSize(16.0f, 16.0f);
    _hmProgressIndicator = [[HMProgressIndicator alloc] initWithFrame:rect];
    [_hmProgressIndicator setStyle:NSProgressIndicatorSpinningStyle];
    [_hmProgressIndicator setDisplayedWhenStopped:NO];
    [_hmProgressIndicator setMinValue:0.0f];
    [_hmProgressIndicator setMaxValue:1.0f];
    [self addSubview:_hmProgressIndicator];
    
    return self;
}

- (void)dealloc
{
    [_closeButton release], _closeButton = nil;
    [_nsProgressIndicator release], _nsProgressIndicator = nil;
    [_hmProgressIndicator release], _hmProgressIndicator = nil;
    
    [super dealloc];
}

//--------------------------------------------------------------//
#pragma mark -- Tab view item --
//--------------------------------------------------------------//

- (HMTabViewItem*)tabViewItem
{
    return _tabViewItem;
}

- (HMTabItemGroupView*)tabItemGroupView
{
    return _tabItemGroupView;
}

- (void)setTabItemGroupView:(HMTabItemGroupView*)tabItemGroupView
{
    _tabItemGroupView = tabItemGroupView;
}

- (NSImageInterpolation)thumbnailInterpolation
{
    return _thumbnailInterpolation;
}

- (void)setThumbnailInterpolation:(NSImageInterpolation)interpolation
{
    if (_thumbnailInterpolation != interpolation) {
        _thumbnailInterpolation = interpolation;
    }
}

//--------------------------------------------------------------//
#pragma mark -- Buttons --
//--------------------------------------------------------------//

- (NSButton*)closeButton
{
    return _closeButton;
}

- (NSProgressIndicator*)nsProgressIndicator
{
    return _nsProgressIndicator;
}

- (HMProgressIndicator*)hmProgressIndicator
{
    return _hmProgressIndicator;
}

//--------------------------------------------------------------//
#pragma mark -- Mouse operation --
//--------------------------------------------------------------//

- (void)mouseUp:(NSEvent*)event
{
    // Select tab
    [[_tabViewItem tabView] selectTabViewItem:_tabViewItem];
}

- (void)mouseDragged:(NSEvent*)event
{
#if 0
    // Create drag image
    NSImage*    image;
    NSImage*    transparentImage;
    NSRect      bounds;
    bounds = [self bounds];
    image = [[NSImage alloc] initWithSize:bounds.size];
    [image autorelease];
    [image setFlipped:[self isFlipped]];
    [image lockFocus];
    [self drawRect:bounds];
    [image unlockFocus];
    
    transparentImage = [[NSImage alloc] initWithSize:bounds.size];
    [transparentImage autorelease];
    [transparentImage lockFocus];
    [image dissolveToPoint:NSZeroPoint fraction:0.7f];
    [transparentImage unlockFocus];
    
    // Write pasteboard
    NSPasteboard*   pboard;
    pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
    [pboard declareTypes:[NSArray arrayWithObject:HMTabItemViewPboardType] owner:nil];
    
    // Start dragging
    NSPoint point;
    point.x = 0;
    point.y = bounds.size.height;
    [self dragImage:transparentImage 
            at:point 
            offset:NSZeroSize 
            event:event 
            pasteboard:pboard 
            source:self 
            slideBack:YES];
#endif
}

//--------------------------------------------------------------//
#pragma mark -- Close button and progress indicator --
//--------------------------------------------------------------//

- (void)_updateButtons
{
    // Get bounds
    NSRect  bounds;
    bounds = [self bounds];
    
    // Check thumbnail
    BOOL    hasThumbnail;
    hasThumbnail = [[_tabViewItem tabView] hasThumbnail];
    
    // Get number of tab
    int numberOfTab;
    numberOfTab = [[_tabViewItem tabView] numberOfTabViewItems];
    
    // Update close button frame
    NSSize  buttonSize;
    NSRect  buttonFrame;
    buttonSize = [_closeButton frame].size;
    
    if (hasThumbnail) {
        buttonFrame.origin.x = 6.0f;
        buttonFrame.origin.y = 5.0f;
    }
    else {
        buttonFrame.origin.x = 6.0f;
        buttonFrame.origin.y = 7.0f;
    }
    buttonFrame.size = buttonSize;
    
    [_closeButton setFrame:buttonFrame];
    [_closeButton setHidden:numberOfTab <= 1];
    
    // Update progress indicator frame
    NSSize  indicatorSize;
    NSRect  indicatorFrame;
    indicatorSize = [_nsProgressIndicator frame].size;
    
    if (hasThumbnail) {
        indicatorFrame.origin.x = 
                floor((bounds.size.width - indicatorSize.width) / 2.0f);
        indicatorFrame.origin.y = 
                floor((bounds.size.height - indicatorSize.height) / 2.0f + 6.0f);
        indicatorFrame.size = indicatorSize;
        [_nsProgressIndicator setFrame:indicatorFrame];
        
        [_hmProgressIndicator setHidden:YES];
    }
    else {
        indicatorFrame.origin.x = bounds.size.width - 3.0f - indicatorSize.width;
        indicatorFrame.origin.y = bounds.size.height - 5.0f - indicatorSize.height;
        indicatorFrame.size = indicatorSize;
        [_hmProgressIndicator setFrame:indicatorFrame];
        
        [_nsProgressIndicator setHidden:YES];
    }
}

- (void)setFrame:(NSRect)frame
{
    [super setFrame:frame];
    
    // Update buttons
    [self _updateButtons];
}

- (void)setBounds:(NSRect)bounds
{
    [super setBounds:bounds];
    
    // Update buttons
    [self _updateButtons];
}
 
//--------------------------------------------------------------//
#pragma mark -- Drawing --
//--------------------------------------------------------------//

- (BOOL)isFlipped
{
    return YES;
}

- (void)_drawThumbnailInRect:(NSRect)rect
{
    // Get tab view
    HMTabView*  tabView;
    tabView = [_tabViewItem tabView];
    
    // Get tab position
    HMTabViewPosition   tabPosition;
    tabPosition = [tabView tabViewPosition];
    
    // x, y, w, h
    float x, y, w, h;
    x = rect.origin.x;
    y = rect.origin.y;
    w = rect.size.width;
    h = rect.size.height;
    
    // Check flip
    BOOL    isFlipped;
    isFlipped = [self isFlipped];
    
    // Decide this tab is selected or not
    BOOL    isSelected;
    BOOL    isKeyWindow;
    isSelected = _tabViewItem == [tabView selectedTabViewItem];
    isKeyWindow = [[NSApplication sharedApplication] isActive] && [[tabView window] isKeyWindow];
    
    // Decide line color
    NSColor*    lineColor;
    lineColor = [HMTabView lineColorWithWindow:[tabView window]];
    
    // Save graphic state
    NSGraphicsContext*  context;
    context = [NSGraphicsContext currentContext];
    [context saveGraphicsState];
    
    if ([context imageInterpolation] != _thumbnailInterpolation) {
        [context setImageInterpolation:_thumbnailInterpolation];
    }
    
    // Decide image rect
    NSRect  imageRect;
    imageRect.origin.x = rect.origin.x + HMTabViewThumbnailPaddingLeft;
    if (isFlipped) {
        imageRect.origin.y = rect.origin.y + HMTabViewThumbnailPaddingTop;
    }
    else {
        imageRect.origin.y = rect.origin.y + HMTabViewThumbnailPaddingBottom;
    }
    imageRect.size.width = rect.size.width - HMTabViewThumbnailPaddingLeft - HMTabViewThumbnailPaddingRight;
    if (isFlipped) {
        imageRect.size.height = rect.size.height - HMTabViewThumbnailPaddingTop - HMTabViewThumbnailPaddingBottom + 2;
    }
    else {
        imageRect.size.height = rect.size.height - HMTabViewThumbnailPaddingTop - HMTabViewThumbnailPaddingBottom;
    }
    
    // Fill bezel
    NSRect          gridRect;
    NSBezierPath*   gridPath;
    gridRect.origin.x = imageRect.origin.x + 0.5f;
    gridRect.origin.y = imageRect.origin.y + 0.5f;
    gridRect.size.width = imageRect.size.width - 1.0f;
    gridRect.size.height = imageRect.size.height - 1.0f;
    gridPath = [NSBezierPath ellipseInRect:gridRect withRadius:5.0f];
    [[NSColor whiteColor] set];
    [gridPath fill];
    
    // Clip path
    [gridPath addClip];
    
    //
    // Draw image
    //
    
    NSImage*    thumbnailImage;
    thumbnailImage = [_tabViewItem thumbnailImage];
    if (thumbnailImage) {
        // Get image size
        NSSize  imageSize;
        imageSize = [thumbnailImage size];
        
        // Decide src rect and dest rect
        NSRect  srcRect, destRect;
        
        // Inset image rect
        destRect = imageRect;
        
        // Src rect width is equal with image width
        srcRect.size.width = imageSize.width;
        
        // When image size width is larther than dest rect width
        if (imageSize.width > destRect.size.width) {
            // Shrink height
            srcRect.size.height = destRect.size.height / destRect.size.width * imageSize.width;
        }
        // Other case
        else {
            srcRect.size.height = imageSize.height;
        }
        
        // Decide origin
        srcRect.origin.x = 0;
        if (isFlipped) {
            srcRect.origin.y = 0;
        }
        else {
            if (imageSize.height > srcRect.size.height) {
                srcRect.origin.y = imageSize.height - srcRect.size.height;
            }
            else {
                srcRect.origin.y = imageSize.height;
            }
        }
        
        // Draw  image
        [thumbnailImage drawInRect:destRect 
                fromRect:srcRect operation:NSCompositeSourceOver fraction:1.0f];
    }
    
    //
    // Draw progress
    //
    
    if ([_tabViewItem isWorking]) {
        static NSImage* _progressImage = nil;
        static NSRect   _progressImageRect;
        if (!_progressImage) {
            _progressImage = [[NSImage imageNamed:@"tabProgress"] retain];
            _progressImageRect.origin = NSZeroPoint;
            _progressImageRect.size = [_progressImage size];
        }
        
        // Decide progress rect
        float   estimatedProgress;
        NSRect  progressRect;
        estimatedProgress = [_tabViewItem estimatedProgress];
        progressRect.size.width = imageRect.size.width;
        progressRect.size.height = imageRect.size.height * estimatedProgress;
        if (isFlipped) {
            progressRect.origin.x = imageRect.origin.x;
            progressRect.origin.y = imageRect.origin.y + imageRect.size.height - progressRect.size.height;
        }
        else {
            progressRect.origin = imageRect.origin;
        }
        [_progressImage drawInRect:progressRect 
                fromRect:_progressImageRect operation:NSCompositeSourceOver fraction:1.0f];
    }
    
    // Restore graphic state
    [context restoreGraphicsState];
    
    //
    // Draw selected background
    //
    
    if (isSelected) {
        // Decide fill rect
        NSRect  fillRect;
        fillRect.origin.x = x + 1.0f;
        fillRect.origin.y = y + 1.0f;
        fillRect.size.width = w - 2.0f;
        fillRect.size.height = h - 1.0f;
        
        NSRect      imgRect;
        NSImage*    image;
        
        // Draw left bottom
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedLeftBottomRect.size.height;
        }
        else {
            imgRect.origin = fillRect.origin;
        }
        imgRect.size = _selectedLeftBottomRect.size;
        image = isKeyWindow ? _selectedLeftBottomImage : _selectedOutLeftBottomImage;
        [image drawInRect:imgRect fromRect:_selectedLeftBottomRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw left middle
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x;
            imgRect.origin.y = fillRect.origin.y + _selectedLeftTopRect.size.height;
        }
        else {
            imgRect.origin.x = fillRect.origin.x;
            imgRect.origin.y = fillRect.origin.y + _selectedLeftBottomRect.size.height;
        }
        imgRect.size.width = _selectedLeftMiddleRect.size.width;
        imgRect.size.height = fillRect.size.height - _selectedLeftBottomRect.size.height - _selectedLeftTopRect.size.height;
        image = isKeyWindow ? _selectedLeftMiddleImage : _selectedOutLeftMiddleImage;
        [image drawInRect:imgRect fromRect:_selectedLeftMiddleRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw left top
        if (isFlipped) {
            imgRect.origin = fillRect.origin;
        }
        else {
            imgRect.origin.x = fillRect.origin.x;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedLeftTopRect.size.height;
        }
        imgRect.size = _selectedLeftTopRect.size;
        image = isKeyWindow ? _selectedLeftTopImage : _selectedOutLeftTopImage;
        [image drawInRect:imgRect fromRect:_selectedLeftTopRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw middle bottom
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x + _selectedLeftBottomRect.size.width;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedLeftBottomRect.size.height;
        }
        else {
            imgRect.origin.x = fillRect.origin.x + _selectedLeftBottomRect.size.width;
            imgRect.origin.y = fillRect.origin.y;
        }
        imgRect.size.width = fillRect.size.width - _selectedLeftBottomRect.size.width - _selectedRightBottomRect.size.width;
        imgRect.size.height = _selectedMiddleBottomRect.size.height;
        image = isKeyWindow ? _selectedMiddleBottomImage : _selectedOutMiddleBottomImage;
        [image drawInRect:imgRect fromRect:_selectedMiddleBottomRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw middle top
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x + _selectedLeftTopRect.size.width;
            imgRect.origin.y = fillRect.origin.y;
        }
        else {
            imgRect.origin.x = fillRect.origin.x + _selectedLeftTopRect.size.width;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedMiddleTopRect.size.height;
        }
        imgRect.size.width = fillRect.size.width - _selectedLeftTopRect.size.width - _selectedRightTopRect.size.width;
        imgRect.size.height = _selectedMiddleTopRect.size.height;
        image = isKeyWindow ? _selectedMiddleTopImage : _selectedOutMiddleTopImage;
        [image drawInRect:imgRect fromRect:_selectedMiddleTopRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw right bottom
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightBottomRect.size.width;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedRightBottomRect.size.height;
        }
        else {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightBottomRect.size.width;
            imgRect.origin.y = fillRect.origin.y;
        }
        imgRect.size = _selectedRightBottomRect.size;
        image = isKeyWindow ? _selectedRightBottomImage : _selectedOutRightBottomImage;
        [image drawInRect:imgRect fromRect:_selectedRightBottomRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw middle bottom
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightMiddleRect.size.width;
            imgRect.origin.y = fillRect.origin.y + _selectedRightTopRect.size.height;
        }
        else {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightMiddleRect.size.width;
            imgRect.origin.y = fillRect.origin.y + _selectedRightBottomRect.size.height;
        }
        imgRect.size.width = _selectedRightMiddleRect.size.width;
        imgRect.size.height = fillRect.size.height - _selectedRightBottomRect.size.height - _selectedRightTopRect.size.height;
        image = isKeyWindow ? _selectedRightMiddleImage : _selectedOutRightMiddleImage;
        [image drawInRect:imgRect fromRect:_selectedRightMiddleRect operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw middle top
        if (isFlipped) {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightTopRect.size.width;
            imgRect.origin.y = fillRect.origin.y;
        }
        else {
            imgRect.origin.x = fillRect.origin.x + fillRect.size.width - _selectedRightTopRect.size.width;
            imgRect.origin.y = fillRect.origin.y + fillRect.size.height - _selectedRightTopRect.size.height;
        }
        imgRect.size = _selectedRightTopRect.size;
        image = isKeyWindow ? _selectedRightTopImage : _selectedOutRightTopImage;
        [image drawInRect:imgRect fromRect:_selectedRightTopRect operation:NSCompositeSourceOver fraction:1.0f];
    }
    
    //
    // Draw grid
    //
    
    else {
        [[NSColor grayColor] set];
        [gridPath stroke];
    }
    
    //
    // Draw label
    //
    
    NSAttributedString* attributedLabel = nil;
    if (isSelected && isKeyWindow) {
        attributedLabel = [_tabViewItem selectedAttributedLabel];
    }
    else {
        attributedLabel = [_tabViewItem attributedLabel];
    }
    
    if (attributedLabel) {
        // Decide label rect
        NSRect  labelRect;
        if (isFlipped) {
            labelRect = NSInsetRect(rect, 7.0f, 4.0f);
        }
        else {
            labelRect = NSInsetRect(rect, 7.0f, 3.0f);
        }
        
        if (![_closeButton isHidden]) {
            labelRect.origin.x += 14.0f;
            labelRect.size.width -= 14.0f;
        }
        
        // Draw label
        [attributedLabel drawInRect:labelRect];
    }
}

- (void)_drawShiira2LabelInRect:(NSRect)rect
{
    // Get tab view
    HMTabView*  tabView;
    tabView = [_tabViewItem tabView];
    
    // Get tab position
    HMTabViewPosition   tabPosition;
    tabPosition = [tabView tabViewPosition];
    
    // x, y, w, h
    float x, y, w, h;
    x = ceil(rect.origin.x);
    y = ceil(rect.origin.y);
    w = ceil(rect.size.width);
    h = ceil(rect.size.height);
    
    // Decide this tab is selected or not
    BOOL    isSelected;
    isSelected = _tabViewItem == [tabView selectedTabViewItem];
    
    // Decide line color
    NSColor*    lineColor;
    NSColor*    highlightColor;
    lineColor = [HMTabView lineColorWithWindow:[tabView window]];
    highlightColor = [HMTabView highlightLineColorWithWindow:[tabView window]];
    
    //
    // Draw tab
    //
    
    if (isSelected) {
        // Draw left image
        NSRect  tabBarRect;
        tabBarRect.origin.x = x;
        tabBarRect.origin.y = y + 1;
        tabBarRect.size = _tabBarLeftRect.size;
        [_tabBarLeftImage drawInRect:tabBarRect fromRect:_tabBarLeftRect 
                operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw right image
        tabBarRect.origin.x = x + w - _tabBarRightRect.size.width;
        tabBarRect.origin.y = y + 1;
        tabBarRect.size = _tabBarRightRect.size;
        [_tabBarRightImage drawInRect:tabBarRect fromRect:_tabBarRightRect 
                operation:NSCompositeSourceOver fraction:1.0f];
        
        // Draw middle image
        tabBarRect.origin.x = x + _tabBarLeftRect.size.width;
        tabBarRect.origin.y = y + 1;
        tabBarRect.size.width = w - _tabBarLeftRect.size.width - _tabBarRightRect.size.width;
        tabBarRect.size.height = _tabBarMiddleRect.size.height;
        [_tabBarMiddleImage drawInRect:tabBarRect fromRect:_tabBarMiddleRect 
                operation:NSCompositeSourceOver fraction:1.0f];
    }
    else {
        // Check right tab
        int     index, selectedIndex;
        BOOL    isSelectedVisible;
        index = [tabView indexOfTabViewItem:_tabViewItem];
        selectedIndex = [tabView indexOfSelectedTabViewItem];
#if 1
        isSelectedVisible = YES;
#else
        isSelectedVisible = [_tabItemGroupView isTabItemVisibleAtIndex:selectedIndex];
#endif
        if (selectedIndex != index + 1 || !isSelectedVisible) {
            // Draw line
            [lineColor set];
            
            switch (tabPosition) {
            case HMTabViewTop: {
                [NSBezierPath strokeLineFromPoint:NSMakePoint(x + w - 0.5f, y) 
                        toPoint:NSMakePoint(x + w - 0.5f, y + h - 4.0f)];
                break;
            }
            }
        }
    }
    
    //
    // Draw label
    //
    
    NSAttributedString* noThumbnailAttributedLabel;
    noThumbnailAttributedLabel = [_tabViewItem noThumbnailAttributedLabel];
    if (noThumbnailAttributedLabel) {
        // Decide label rect
        NSRect  labelRect;
        labelRect = NSInsetRect(rect, 4.0f, 6.0f);
        if (![_closeButton isHidden]) {
            labelRect.origin.x += 14.0f;
            labelRect.size.width -= 14.0f;
        }
        if ([_tabViewItem isWorking]) {
            labelRect.size.width -= 16.0f;
        }
        
        // Draw label
        [noThumbnailAttributedLabel drawInRect:labelRect];
    }
}

- (void)drawRect:(NSRect)rect
{
    if (!_tabViewItem) {
        return;
    }
    
    // Get bounds
    NSRect  bounds;
    bounds = [self bounds];
    
    // Check flip
    static BOOL _isFlipChecked = NO;
    if (!_isFlipChecked) {
        _isFlipChecked = YES;
        
        // Check flip
        BOOL    isFlipped;
        isFlipped = [self isFlipped];
        
        [_selectedLeftBottomImage setFlipped:isFlipped];
        [_selectedLeftMiddleImage setFlipped:isFlipped];
        [_selectedLeftTopImage setFlipped:isFlipped];
        [_selectedMiddleBottomImage setFlipped:isFlipped];
        [_selectedMiddleMiddleImage setFlipped:isFlipped];
        [_selectedMiddleTopImage setFlipped:isFlipped];
        [_selectedRightBottomImage setFlipped:isFlipped];
        [_selectedRightMiddleImage setFlipped:isFlipped];
        [_selectedRightTopImage setFlipped:isFlipped];
        
        [_selectedOutLeftBottomImage setFlipped:isFlipped];
        [_selectedOutLeftMiddleImage setFlipped:isFlipped];
        [_selectedOutLeftTopImage setFlipped:isFlipped];
        [_selectedOutMiddleBottomImage setFlipped:isFlipped];
        [_selectedOutMiddleMiddleImage setFlipped:isFlipped];
        [_selectedOutMiddleTopImage setFlipped:isFlipped];
        [_selectedOutRightBottomImage setFlipped:isFlipped];
        [_selectedOutRightMiddleImage setFlipped:isFlipped];
        [_selectedOutRightTopImage setFlipped:isFlipped];
        
        [_tabBarLeftImage setFlipped:isFlipped];
        [_tabBarMiddleImage setFlipped:isFlipped];
        [_tabBarRightImage setFlipped:isFlipped];
    }
    
    // Draw thumbnail
    if ([[_tabViewItem tabView] hasThumbnail]) {
        [self _drawThumbnailInRect:bounds];
    }
    
    // Draw label
    else {
        [self _drawShiira2LabelInRect:bounds];
    }
}

//--------------------------------------------------------------//
#pragma mark -- Delegate --
//--------------------------------------------------------------//

- (id)delegate
{
    return _delegate;
}

- (void)setDelegate:(id)delegate
{
    _delegate = delegate;
}

//--------------------------------------------------------------//
#pragma mark -- Context menu --
//--------------------------------------------------------------//

- (NSMenu*)menuForEvent:(NSEvent*)event
{
    if ([_delegate respondsToSelector:@selector(tabItemView:menuForEvent:)]) {
        return [_delegate tabItemView:self menuForEvent:event];
    }
    
    return [self menu];
}

@end
