/*
HMLabelContentView.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 "HMLabelContentView.h"

static NSDictionary*    _labelAttr = nil;
static NSDictionary*    _subLabelAttr = nil;

@implementation HMLabelContentView : NSView

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

+ (void)load
{
    NSAutoreleasePool*  pool;
    pool = [[NSAutoreleasePool alloc] init];
    
    if (!_labelAttr) {
        NSMutableParagraphStyle* paragraphStyle;
        paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
        [paragraphStyle setAlignment:NSCenterTextAlignment];
        
        NSShadow*   shadow;
        shadow = [[NSShadow alloc] init];
        [shadow setShadowOffset:NSMakeSize(0.0, -1.0f)];
        [shadow setShadowBlurRadius:0.0f];
        [shadow setShadowColor:[[NSColor blackColor] colorWithAlphaComponent:0.5f]];
        
        _labelAttr = [[NSDictionary dictionaryWithObjectsAndKeys:
                [NSFont systemFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, 
                [NSColor whiteColor], NSForegroundColorAttributeName, 
                paragraphStyle, NSParagraphStyleAttributeName, 
                shadow, NSShadowAttributeName, 
                nil] retain];
        _subLabelAttr = [[NSDictionary dictionaryWithObjectsAndKeys:
                [NSFont labelFontOfSize:[NSFont labelFontSize]], NSFontAttributeName, 
                [NSColor whiteColor], NSForegroundColorAttributeName, 
                paragraphStyle, NSParagraphStyleAttributeName, 
                shadow, NSShadowAttributeName, 
                nil] retain];
        
        [paragraphStyle release];
        [shadow release];
    }
    
    [pool release];
}

- (void)dealloc
{
    [_label release], _label = nil;
    [_subLabel release], _subLabel = nil;
    
    [super dealloc];
}

//--------------------------------------------------------------//
#pragma mark -- Label --
//--------------------------------------------------------------//

- (NSString*)label
{
    return [[_label copy] autorelease];
}

- (void)setLabel:(NSString*)label
{
    [_label release];
    _label = [label copy];
    
    [self setNeedsDisplay:YES];
}

- (NSString*)subLabel
{
    return [[_subLabel copy] autorelease];
}

- (void)setSubLabel:(NSString*)subLabel
{
    [_subLabel release];
    _subLabel = [subLabel copy];
    
    [self setNeedsDisplay:YES];
}

//--------------------------------------------------------------//
#pragma mark -- Positioning --
//--------------------------------------------------------------//

- (void)setCenterPoint:(NSPoint)point
{
    _centerPoint = point;
    
    // Move window
    NSWindow*   window;
    NSRect      frame;
    window = [self window];
    frame = [window frame];
    [window setFrameOrigin:
            NSMakePoint(point.x - frame.size.width / 2.0f, point.y - frame.size.height / 2.0f)];
}

static int  _hMargin = 4, _vMargin = 2;

- (void)sizeToFit
{
    NSAttributedString* attrStr;
    NSSize              labelSize = NSZeroSize, subLabelSize = NSZeroSize;
    
    // Calc label size
    if (_label) {
        attrStr = [[NSAttributedString alloc] initWithString:_label attributes:_labelAttr];
        labelSize = [attrStr size];
        [attrStr release];
    }
    
    // Calc sub label size
    if (_subLabel) {
        attrStr = [[NSAttributedString alloc] initWithString:_subLabel attributes:_subLabelAttr];
        subLabelSize = [attrStr size];
        [attrStr release];
    }
    
    // Union size
    NSSize  size;
    size.width = labelSize.width > subLabelSize.width ? labelSize.width : subLabelSize.width;
    size.width += _hMargin * 2;
    size.height = labelSize.height + subLabelSize.height;
    size.height += _vMargin * 2;
    
    static int  _maxWidth = 240, _minWidth = 40;
    if (size.width > _maxWidth) {
        size.width = _maxWidth;
    }
    if (size.width < _minWidth) {
        size.width = _minWidth;
    }
    
    // Set frame
    NSWindow*   window;
    NSPoint     centerPoint;
    NSRect      frame;
    window = [self window];
    frame = [window frame];
    centerPoint = _centerPoint;
    if (NSEqualPoints(centerPoint, NSZeroPoint)) {
        centerPoint.x = frame.origin.x + frame.size.width / 2.0f;
        centerPoint.y = frame.origin.y + frame.size.height / 2.0f;
    }
    
    frame.origin.x = centerPoint.x - size.width / 2.0f;
    frame.origin.y = centerPoint.y - size.height / 2.0f;
    frame.size = size;
    [window setFrame:frame display:YES];
}

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

- (id)mouseListener
{
    return _mouseListener;
}

- (void)setMouseListener:(id)mouseListener
{
    _mouseListener = mouseListener;
}

- (NSEvent*)_convertEventForMouseListener:(NSEvent*)event
{
    if (!_mouseListener) {
        return nil;
    }
    
    // Convert mouse location
    NSWindow*   window;
    NSWindow*   listenerWindow;
    NSPoint     point;
    window = [self window];
    listenerWindow = [_mouseListener window];
    point = [event locationInWindow];
    point = [window convertBaseToScreen:point];
    point = [listenerWindow convertScreenToBase:point];
    
    // Create event with converted point
    NSEvent*    convertedEvent;
    convertedEvent = [NSEvent mouseEventWithType:[event type] 
            location:point 
            modifierFlags:[event modifierFlags] 
            timestamp:[event timestamp] 
            windowNumber:[listenerWindow windowNumber] 
            context:[event context] 
            eventNumber:[event eventNumber] 
            clickCount:[event clickCount] 
            pressure:[event pressure]];
    
    return convertedEvent;
}

- (void)mouseDown:(NSEvent*)event
{
    if (!_mouseListener) {
        return;
    }
    
    // Notify converted event
    [_mouseListener mouseDown:[self _convertEventForMouseListener:event]];
}

- (void)mouseDragged:(NSEvent*)event
{
    if (!_mouseListener) {
        return;
    }
    
    // Notify converted event
    [_mouseListener mouseDragged:[self _convertEventForMouseListener:event]];
}

//--------------------------------------------------------------//
#pragma mark -- Drawing --
//--------------------------------------------------------------//

- (void)drawRect:(NSRect)rect
{
    // Get frame
    NSRect  frame;
    frame = [self frame];
    
    // Clear rect
    [[NSColor clearColor] set];
    NSRectFill(rect);
    
    // Create edge path
    NSRect          edgeRect;
    NSBezierPath*   edgePath;
    edgeRect = NSInsetRect(frame, 1.0f, 1.0f);
    edgePath = [NSBezierPath ellipseInRect:edgeRect withRadius:5.0f];
    
    // Draw backgound
    [[NSColor colorWithCalibratedWhite:0.0f alpha:0.75f] set];
    [edgePath fill];
    
    // Draw edge
    //[[NSColor whiteColor] set];
    //[edgePath setLineWidth:2.0f];
    //[edgePath stroke];
    
    NSAttributedString* attrStr;
    NSSize              attrStrSize;
    NSRect              attrStrFrame;
    
    // Draw label
    if (_label) {
        attrStr = [[NSAttributedString alloc] initWithString:_label attributes:_labelAttr];
        attrStrSize = [attrStr size];
        attrStrFrame.origin.x = frame.origin.x + _hMargin;
        if (!_subLabel) {
            attrStrFrame.origin.y = frame.origin.y + _vMargin;
        }
        else {
            attrStrFrame.origin.y = frame.origin.y + frame.size.height / 2.0f;
        }
        attrStrFrame.size.width = frame.size.width - _hMargin * 2;
        attrStrFrame.size.height = attrStrSize.height;
        
        [attrStr drawInRect:attrStrFrame];
        [attrStr release];
    }
    
    // Draw sub label
    if (_subLabel) {
        attrStr = [[NSAttributedString alloc] initWithString:_subLabel attributes:_subLabelAttr];
        attrStrSize = [attrStr size];
        attrStrFrame.origin.x = frame.origin.x + _hMargin;
        if (!_label) {
            attrStrFrame.origin.y = frame.origin.y + _vMargin;
        }
        else {
            attrStrFrame.origin.y = frame.origin.y + frame.size.height / 2.0f - attrStrSize.height;
        }
        attrStrFrame.size.width = frame.size.width - _hMargin * 2;
        attrStrFrame.size.height = attrStrSize.height;
        
        [attrStr drawInRect:attrStrFrame];
        [attrStr release];
    }
}

@end
