//
//  MFPanel.mm
//  MySQLWorkbench
//
//  Created by Alfredo Kojima on 7/Feb/09.
//  Copyright 2009 Sun Microsystems Inc. All rights reserved.
//

#import "MFPanel.h"

#include "mforms/mforms.h"

#import "MFRadioButton.h" // for hadnling radio groups


@interface MFPanelContent : NSView
{
  MFPanelImpl *panel;
  float mPadding;
}
@end


@implementation MFPanelContent

- (id)initWithPanel:(MFPanelImpl*)aPanel
{
  NSRect frame= [aPanel frame];
  frame.origin= NSMakePoint(0, 0);
  self= [super initWithFrame:frame];
  if (self)
  {
    panel= aPanel;
  }
  return self;
}

/*
- (void)drawRect:(NSRect)frame{
  [[NSColor magentaColor] set];
  NSFrameRect(NSInsetRect([self frame], 2, 1));
}
*/

- (BOOL)isFlipped
{
  return YES;
}


- (void)setPadding:(float)pad
{
  mPadding= pad;
}


- (void)subviewMinimumSizeChanged
{
  NSSize minSize= [[[self subviews] lastObject] minimumSize];
  NSSize size= [self frame].size;
  
  // size of some subview has changed, we check if our current size is enough
  // to fit it and if not, request forward the size change notification to superview
  
  if (minSize.width != size.width || minSize.height != size.height)
    [panel subviewMinimumSizeChanged];
  else
    [[[self subviews] lastObject] setFrameSize: size];    
}


- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize
{
  id content= [[self subviews] lastObject];
  NSSize size= [self frame].size;
  size.width= NSWidth([self frame]) - 2*mPadding;
  // size.height= [content minimumSize].height;
  [content setFrame: NSMakeRect(mPadding, mPadding, size.width, size.height)];
}


- (NSSize)minimumSize
{
  NSSize size= [[[self subviews] lastObject] minimumSize];
  size.width+= 2 * mPadding;
  size.height+= 2 * mPadding;
  return size;
}


@end




@implementation MFPanelImpl

- (id)initWithObject:(::mforms::Panel*)aPanel type:(::mforms::PanelType)type
{
  self= [super initWithFrame:NSMakeRect(10, 10, 10, 10)];
  if (self)
  {
    NSRect frame;
    NSRect content= NSMakeRect(10, 10, 10, 10);

    mOwner= aPanel;
    mOwner->set_data(self);
    
    switch (type)
    {
      case mforms::TransparentPanel: // just a container with no background
        [self setTransparent: YES];
        [self setTitlePosition: NSNoTitle];
        break;
      case mforms::FilledPanel:      // just a container with color filled background
        [self setTransparent: NO];
        [self setBorderType: NSNoBorder];
        [self setTitlePosition: NSNoTitle];
        break;
      case mforms::BorderedPanel:    // container with native border
        [self setBorderType: NSBezelBorder];
        [self setTitlePosition: NSNoTitle];
        break;
      case mforms::LineBorderPanel:  // container with a solid line border
        [self setBorderType: NSLineBorder];
        [self setTitlePosition: NSNoTitle];
        break;
      case mforms::TitledBoxPanel:   // native grouping box with a title with border
        [self setBorderType: NSBezelBorder];
        break;
      case mforms::TitledGroupPanel: // native grouping container with a title (may have no border) 
        [self setBorderType: NSNoBorder];
        break;
      case mforms::CheckBoxTitlePanel:// container with checkbox
        [self setBorderType: NSBezelBorder];        
        mCheckButton= [[NSButtonCell alloc] initTextCell:@""];
        [mCheckButton setControlSize: NSSmallControlSize];
        [mCheckButton setFont: [NSFont boldSystemFontOfSize: [NSFont systemFontSizeForControlSize: NSSmallControlSize]]];
        [mCheckButton setButtonType: NSSwitchButton];
        [mCheckButton setAction: @selector(toggleCheck:)];
        [mCheckButton setTarget: self];
        [super setTitle: @""];
        break;
    }
    
    [self setContentViewMargins: NSMakeSize(0, 0)];
    [self setFrameFromContentFrame: content];
    frame= [self frame];
    // calculate the offsets the NSBox adds to the contentView
    mTopLeftOffset.x= NSMinX(content) - NSMinX(frame);
    mTopLeftOffset.y= NSMinY(content) - NSMinY(frame);
    mBottomRightOffset.x= NSMaxX(frame) - NSMaxX(content);
    mBottomRightOffset.y= MAX(NSMaxY(frame) - NSMaxY(content), [mCheckButton cellSize].height);

    [super setContentView: [[[MFPanelContent alloc] initWithPanel: self] autorelease]];
  }
  return self;
}


- (void) dealloc
{
  [mCheckButton release];
  [super dealloc];
}

- (NSRect)titleRect
{
  NSRect rect;
  rect= [super titleRect];
  if (mCheckButton)
  {
    rect.origin.y-= 3;
    rect.size= [mCheckButton cellSize];
    rect.size.width+= 4;
  }
  return rect;
}


- (void)toggleCheck:(id)sender
{
  mOwner->check_toggled();
}


- (void)mouseDown:(NSEvent*)event
{
  if (mCheckButton)
  {
    [mCheckButton trackMouse:event inRect:[self titleRect]
                      ofView:self
                untilMouseUp:NO];
    [self setNeedsDisplay:YES];
  }
}


- (void)mouseUp:(NSEvent*)event
{
  if (mCheckButton)
  {
    [self setNeedsDisplay:YES];
  }
}


- (void)drawRect:(NSRect)rect
{
  [super drawRect:rect];

  [mCheckButton drawWithFrame:[self titleRect] inView:self];
}


- (mforms::Object*)mformsObject
{
  return mOwner;
}


- (NSSize)minimumSize
{
  NSSize size= [[self contentView] minimumSize];

  size.width += mTopLeftOffset.x + mBottomRightOffset.x;
  size.height += mTopLeftOffset.y + mBottomRightOffset.y;
    
  return size;
}


- (void)subviewMinimumSizeChanged
{
  NSSize minSize= [self minimumSize];
  NSSize size= [self frame].size;
  
  // size of some subview has changed, we check if our current size is enough
  // to fit it and if not, request forward the size change notification to superview
  
  if (minSize.width != size.width || minSize.height != size.height)
  {
    if ([self superview])
    {
      [[self superview] subviewMinimumSizeChanged];
      return;
    }
    else
      [self setFrameSize: minSize];
  }
  [self resizeSubviewsWithOldSize:size];
}


- (void)setTag:(NSInteger)tag
{
  mTag= tag;
}


- (NSInteger)tag
{
  return mTag;
}


- (void)setPadding:(float)padding
{
  [[self contentView] setPadding: padding];
}


- (void)setContentView:(NSView*)content
{
  [[self contentView] addSubview: content];
  [self subviewMinimumSizeChanged];
}


- (void)setTitle:(NSString*)title
{
  if (mCheckButton)
    [mCheckButton setTitle: title];
  else
    [super setTitle: title];
}



- (void)setSelectedRadio:(NSButton*)radio inSubview:(NSView*)view
{
  for (id subview in [view subviews])
  {
    if (subview != radio && [subview isKindOfClass:[MFRadioButtonImpl class]])
    {
      if ([subview state] == NSOnState)
      {
        [subview setState: NSOffState];
        [subview performCallback:nil];
      }
    }
    else
      [self setSelectedRadio: radio inSubview: subview];
  }
}


- (void)setEnabled:(BOOL)flag
{
  for (id view in [[self contentView] subviews])
  {
    if ([view respondsToSelector:@selector(setEnabled:)])
      [view setEnabled: flag];
  }
}


- (void)setSelectedRadio:(NSButton*)radio
{
  [self setSelectedRadio:radio inSubview:self];
}



static bool panel_create(::mforms::Panel *self, ::mforms::PanelType type)
{
  [[[MFPanelImpl alloc] initWithObject:self type:type] autorelease];
    
  return true;
}


static void panel_set_title(::mforms::Panel *self, const std::string &text)
{
  if ( self )
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      [panel setTitle:wrap_nsstring(text)];
    }
  }
}



static void panel_set_back_color(mforms::Panel *self, const std::string &color)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      unsigned int pixel;
      NSScanner *scanner = [NSScanner scannerWithString:wrap_nsstring(color)];
      [scanner scanHexInt: &pixel];

      [panel setTransparent: NO];
      [panel setFillColor: [NSColor colorWithCalibratedRed:(pixel>>16)&0xff
                                                    green:(pixel>>8)&0xff
                                                     blue:pixel&0xff
                                                    alpha:1.0]];
    }
  }
}



static void panel_set_active(mforms::Panel *self, bool active)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      [panel->mCheckButton setState: active ? NSOnState : NSOffState];
    }
  }
}


static bool panel_get_active(mforms::Panel *self)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      return [panel->mCheckButton state] == NSOnState;
    }
  }
  return false;
}


static void panel_set_padding(mforms::Panel *self, int padding)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      [panel setPadding: padding];
    }
  }
}


static void panel_add(mforms::Panel *self,mforms::View *view)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      [panel setContentView: view->get_data()];
    }
  }
}


static void panel_remove(mforms::Panel *self, mforms::View *child)
{
  if (self)
  {
    MFPanelImpl* panel = self->get_data();
    
    if ( panel )
    {
      [panel setContentView:nil];
    }
  }
}



void cf_panel_init()
{
  ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();
  
  f->_panel_impl.create= &panel_create;
  f->_panel_impl.set_title= &panel_set_title;
  f->_panel_impl.set_back_color= &panel_set_back_color;
  f->_panel_impl.set_title= &panel_set_title;
  
  f->_panel_impl.set_active= &panel_set_active;
  f->_panel_impl.get_active= &panel_get_active;
  
  f->_panel_impl.set_padding= &panel_set_padding;
  
  f->_panel_impl.add= &panel_add;
  f->_panel_impl.remove= &panel_remove;
}


@end



