/*
**  CriterionObjectView.m
**
**  Copyright (c) 2004
**
**  Author: Yen-Ju Chen <yjchenx@hotmail.com>
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "CriterionObjectView.h"
#include "CriterionView.h"
#include "Constants.h"

#ifdef GNUSTEP
static id clickedPopUpCell = nil;
#endif

#define CellSpace 3

@implementation CriterionObjectView

- (NSString *) _stringFromCriterionDateUnit: (CriterionDateUnit) unit
{
  switch (unit)
    {
      case CriterionSecondUnit:
	return sCriterionSecondUnit;
      case CriterionMinuteUnit:
	return sCriterionMinuteUnit;
      case CriterionHourUnit:
	return sCriterionHourUnit;
      case CriterionDayUnit:
	return sCriterionDayUnit;
      case CriterionWeekUnit:
	return sCriterionWeekUnit;
      case CriterionMonthUnit:
	return sCriterionMonthUnit;
      case CriterionYearUnit:
	return sCriterionYearUnit;
    }
  return nil;
}

- (CriterionDateUnit) _criterionDateUnitFromString: (NSString *) string
{
  if ([string isEqualToString: sCriterionSecondUnit])
    return CriterionSecondUnit;
  else if ([string isEqualToString: sCriterionMinuteUnit])
    return CriterionMinuteUnit;
  else if ([string isEqualToString: sCriterionHourUnit])
    return CriterionHourUnit;
  else if ([string isEqualToString: sCriterionDayUnit])
    return CriterionDayUnit;
  else if ([string isEqualToString: sCriterionWeekUnit])
    return CriterionWeekUnit;
  else if ([string isEqualToString: sCriterionMonthUnit])
    return CriterionMonthUnit;
  else if ([string isEqualToString: sCriterionYearUnit])
    return CriterionYearUnit;
  else
    return CriterionErrorUnit;
}

- (NSRect) _frameOfToTextFieldCell
{
  NSRect bounds = [self bounds];
  NSSize size = [toTextFieldCell cellSize];
  float text_width = (bounds.size.width-size.width)/2;

  return NSMakeRect(text_width, 0, size.width, size.height);
}

- (NSRect) _frameOfUnitPopUpCell
{
  NSRect bounds = [self bounds];
  float button_width, button_height;
  button_width = [unitPopUpCell cellSize].width;
  button_height = [unitPopUpCell cellSize].height;
  if (unitPopUpCellWidth < button_width)
    unitPopUpCellWidth = button_width;

  return NSMakeRect(bounds.size.width-unitPopUpCellWidth, -1,
		    unitPopUpCellWidth, button_height);
}

- (NSRect) _frameOfSelectionPopUpCell
{
  NSRect bounds = [self bounds];
  float button_height, button_width;
  button_height = [selectionPopUpCell cellSize].height;
  //button_width = bounds.size.width;
  button_width = [selectionPopUpCell cellSize].width;

  return NSMakeRect(0, -1, button_width, button_height);
}

- (void) controlTextDidEndEditing: (NSNotification *) not
{
  //NSLog(@"controlTextDidEndEditing");
  id sender = [not object];
  [self controlAction: sender];
}

- (void) controlAction: (id) sender
{
  //NSLog(@"controlAction");
  [target performSelector: selector withObject: self];
}

- (void) setObjectValue: (id) o
{
  NSString *unit;
  id object = AUTORELEASE([o copy]);
  //NSLog(@"CriterionObjectView: set %@", o);
  if ([object isKindOfClass: [NSArray class]] == NO)
    {
      switch(type)
        {
          case CriterionObjectViewTextFieldType:
            [textField setObjectValue: object];
	    break;
          case CriterionObjectViewIsSelectionType:
	    [selectionPopUpCell selectItemWithTitle: object];
	    break;
	}
    }
  else
    {
      if ([object count] < 1) return;
      [textField setObjectValue: [object objectAtIndex: 0]];
      switch(type)
        {
          case CriterionObjectViewInTheRangeType:
	    [toField setObjectValue: [object lastObject]];
	    break;
          case CriterionObjectViewInTheLastType:
	    unit = [self _stringFromCriterionDateUnit: [[object lastObject] intValue]];
	    if (unit != nil)
	      [unitPopUpCell selectItemWithTitle: unit];
	    break;
        }
    }
}

/* return nil if textField is empty */
- (id) objectValue
{
  switch(type)
    {
      case CriterionObjectViewTextFieldType:
        {
	  return AUTORELEASE([[textField stringValue] copy]);
        }
      case CriterionObjectViewInTheRangeType:
        {
	  NSArray *array = [NSArray arrayWithObjects: 
                    AUTORELEASE([[textField stringValue] copy]),
	            AUTORELEASE([[toField stringValue] copy]),
				    nil];
	  return array;
        }
      case CriterionObjectViewInTheLastType:
	{
	  NSString *title = [unitPopUpCell titleOfSelectedItem];
	  CriterionDateUnit unit = [self _criterionDateUnitFromString: title];
	  NSArray *array = [NSArray arrayWithObjects:
                    AUTORELEASE([[textField stringValue] copy]),
	            [NSNumber numberWithInt: unit], nil];
	  return array;
	}
      case CriterionObjectViewIsSelectionType:
	{
	  return AUTORELEASE([[selectionPopUpCell titleOfSelectedItem] copy]);
	}
    }
}

- (void) setSelectionPopUpButtonTitles: (NSArray *) titles
{
  unsigned int index;
  NSString *title;
  [selectionPopUpCell removeAllItems];

  if (([titles count] < 1) || (titles == nil)) return;

  [selectionPopUpCell addItemsWithTitles: AUTORELEASE([titles copy])];

  title = [selectionPopUpCell titleOfSelectedItem];
  if (title)
    index = [selectionPopUpCell indexOfItemWithTitle: title];
  else
    index = 0;

  if (index != NSNotFound)
    [selectionPopUpCell selectItemAtIndex: index];
  else
    [selectionPopUpCell selectItemAtIndex: 0];

  [selectionPopUpCell synchronizeTitleAndSelectedItem];
}

- (void) setFrameSize: (NSSize) size
{
  float text_width, button_width;
  NSRect rect;
  switch(type)
    {
      case CriterionObjectViewTextFieldType:
        {
          [textField setFrameSize: size];
          break;
        }
      case CriterionObjectViewInTheRangeType:
        {
	  NSSize cellSize = [self _frameOfToTextFieldCell].size;
          text_width = (size.width-cellSize.width)/2;
	  [textField setFrameSize: NSMakeSize(text_width-CellSpace, 
			                      size.height)];
	  rect = NSMakeRect(text_width+cellSize.width+CellSpace, 0,
			    text_width-CellSpace, size.height);
	  [toField setFrame: rect];
          break;
        }
      case CriterionObjectViewInTheLastType:
        {
	  button_width = [self _frameOfUnitPopUpCell].size.width;
          [textField setFrameSize: NSMakeSize(size.width-button_width-CellSpace,
	 	 	                       size.height)];
	  break;
        }
    }
  [super setFrameSize: size];
}

- (void) setType: (CriterionObjectViewType) t
{
  NSRect frame = [self bounds];
  NSRect rect;
  float text_width, button_width;
  if (type != t)
    {
      type = t;
      switch(type)
        {
	  case CriterionObjectViewTextFieldType:
  	    {
	      /* Remove others */
	      if ([toField superview])
		[toField removeFromSuperviewWithoutNeedingDisplay];

	      [textField setFrame: frame];
	      if ([textField superview] == nil)
		[self addSubview: textField];
	      break;
	    }
	  case CriterionObjectViewInTheRangeType:
	    {
	      /* Remove others */
	      NSSize cellSize = [self _frameOfToTextFieldCell].size;
	      text_width = (frame.size.width-cellSize.width)/2;
	      rect = NSMakeRect(0, 0, text_width-CellSpace, frame.size.height);
	      [textField setFrame: rect];
	      rect = NSMakeRect(text_width+cellSize.width+CellSpace, 0,
			        text_width-CellSpace, frame.size.height);
	      [toField setFrame: rect];

	      if ([textField superview] == nil)
		[self addSubview: textField];
	      if ([toField superview] == nil)
		[self addSubview: toField];
	      break;
	    }
	  case CriterionObjectViewInTheLastType:
	    {
	      /* Remove others */
	      if ([toField superview])
		[toField removeFromSuperviewWithoutNeedingDisplay];

	      button_width = [self _frameOfUnitPopUpCell].size.width;
	      rect = NSMakeRect(0, 0, frame.size.width-button_width-CellSpace,
			              frame.size.height);
	      [textField setFrame: rect];

	      if ([textField superview] == nil)
		[self addSubview: textField];

	      break;
	    }
	  case CriterionObjectViewIsSelectionType:
  	    {
	      /* Remove others */
	      if ([textField superview])
		[textField removeFromSuperviewWithoutNeedingDisplay];
	      if ([toField superview])
		[toField removeFromSuperviewWithoutNeedingDisplay];
	      break;
	    }
        }
      [self display];
    }
}

#ifdef GNUSTEP
- (void) _handleNotification: (NSNotification*) not
{
  NSString *name = [not name];
  if ([name isEqual: NSMenuDidSendActionNotification] == YES)
    {
      [clickedPopUpCell dismissPopUp];
      [clickedPopUpCell synchronizeTitleAndSelectedItem];
      [self setNeedsDisplay: YES];
    }
}
#endif

- (void) mouseDown: (NSEvent *) event
{
  NSPoint initialLocation = [event locationInWindow];
  NSPoint p = [self convertPoint: initialLocation fromView: nil];
  NSRect rect, bounds = [self bounds];
  switch(type)
    {
      case CriterionObjectViewInTheLastType:
        {
	  rect = [self _frameOfUnitPopUpCell];
	  if (NSMouseInRect(p, rect, YES))
	    {
#ifdef GNUSTEP
              clickedPopUpCell = unitPopUpCell;;
              [unitPopUpCell attachPopUpWithFrame: rect
 		                           inView: self];
              NSWindow *menuWindow = [[[unitPopUpCell menu] menuRepresentation] window];
              NSPoint p = [menuWindow convertScreenToBase: [[self window] convertBaseToScreen: [event locationInWindow]]];
              NSEvent *e = [NSEvent mouseEventWithType: [event type]
                                              location: p
                                         modifierFlags: [event modifierFlags]
                                             timestamp: [event timestamp]
                                          windowNumber: [menuWindow windowNumber]
                                               context: [event context]
                                           eventNumber: [event eventNumber]
                                            clickCount: [event clickCount] 
                                              pressure: [event pressure]];
              [NSApp sendEvent: e];
#else
              BOOL result = [unitPopUpCell trackMouse: event inRect: rect 
                                           ofView: self untilMouseUp: YES];
#endif
	      /* cell size change with title 
	       * recalculate its size */
	      rect = [self _frameOfUnitPopUpCell];
	      rect = NSMakeRect(0, 0, bounds.size.width-rect.size.width-CellSpace,
			              bounds.size.height);
	      [textField setFrame: rect];
	      [self display];
  	      [self controlAction: self];
  	      break;
	    }
	}
      case CriterionObjectViewIsSelectionType:
        {
	  rect = [self _frameOfSelectionPopUpCell];
	  if (NSMouseInRect(p, rect, YES))
	    {
#ifdef GNUSTEP
              clickedPopUpCell = selectionPopUpCell;
              [selectionPopUpCell attachPopUpWithFrame: rect
 		                           inView: self];
              NSWindow *menuWindow = [[[selectionPopUpCell menu] menuRepresentation] window];
              NSPoint p = [menuWindow convertScreenToBase: [[self window] convertBaseToScreen: [event locationInWindow]]];
              NSEvent *e = [NSEvent mouseEventWithType: [event type]
                                              location: p
                                         modifierFlags: [event modifierFlags]
                                             timestamp: [event timestamp]
                                          windowNumber: [menuWindow windowNumber]
                                               context: [event context]
                                           eventNumber: [event eventNumber]
                                            clickCount: [event clickCount] 
                                              pressure: [event pressure]];
              [NSApp sendEvent: e];
#else
              BOOL result = [selectionPopUpCell trackMouse: event inRect: rect 
                                                ofView: self untilMouseUp: YES];
#endif
	      [self display];
  	      [self controlAction: self];
  	      break;
	    }
	}
      default:
	[super mouseDown: event];
    }
}

- (void) drawRect: (NSRect) frame
{
  [super drawRect: frame];
  float button_width, button_height;
  NSRect rect, bounds = [self bounds];

  switch(type)
    {
      case CriterionObjectViewInTheRangeType:
        {
	  rect = [self _frameOfToTextFieldCell];
	  [self lockFocus];
	  [toTextFieldCell drawWithFrame: rect inView: self];
	  [self unlockFocus];
        }
      case CriterionObjectViewInTheLastType:
        {
	  rect = [self _frameOfUnitPopUpCell];
	  [self lockFocus];
	  [unitPopUpCell drawWithFrame: rect inView: self];
	  [self unlockFocus];

          break;
        }
      case CriterionObjectViewIsSelectionType:
        {
	  rect = [self _frameOfSelectionPopUpCell];
	  [self lockFocus];
	  [selectionPopUpCell drawWithFrame: rect inView: self];
	  [self unlockFocus];

          break;
        }
    }
}

- (CriterionObjectViewType) type
{
  return type;
}

- (id) initWithFrame: (NSRect) frame
{
  NSRect bounds;
  self = [super initWithFrame: frame];
  bounds = [self bounds];

  type = CriterionObjectViewTextFieldType;

  textField = [[NSTextField alloc] initWithFrame: bounds];
  [textField setTarget: self];
  [textField setAction: @selector(controlAction:)];
  [textField setDelegate: self];

  toField = [[NSTextField alloc] initWithFrame: bounds];
  [toField setTarget: self];
  [toField setAction: @selector(controlAction:)];
  [toField setDelegate: self];

  toTextFieldCell = [[NSTextFieldCell alloc] initTextCell: sTo];

  unitPopUpCell = [[NSPopUpButtonCell alloc] initTextCell: @"" pullsDown: NO];
  [unitPopUpCell addItemWithTitle: sCriterionSecondUnit];
  [unitPopUpCell addItemWithTitle: sCriterionMinuteUnit];
  [unitPopUpCell addItemWithTitle: sCriterionHourUnit];
  [unitPopUpCell addItemWithTitle: sCriterionDayUnit];
  [unitPopUpCell addItemWithTitle: sCriterionWeekUnit];
  [unitPopUpCell addItemWithTitle: sCriterionMonthUnit];
  [unitPopUpCell addItemWithTitle: sCriterionYearUnit];
  [unitPopUpCell selectItemWithTitle: sCriterionDayUnit];

  selectionPopUpCell = [[NSPopUpButtonCell alloc] initTextCell: @"" 
	                                             pullsDown: NO];
  
  [self addSubview: textField];

  isSmallControlSize = NO;
  unitPopUpCellWidth = 0;

  return self;
}

- (void) dealloc
{
  RELEASE(textField);
  RELEASE(toField);
  RELEASE(toTextFieldCell);
  RELEASE(unitPopUpCell);
  RELEASE(selectionPopUpCell);
  [super dealloc];
}

- (void) setAction: (SEL) s
{
  selector = s;
}

- (SEL) selector
{
  return selector;
}

- (void) setTarget: (id) t
{
  ASSIGN(target, t);
}

- (id) target
{
  return target;
}

- (void) setSmallControlSize: (BOOL) flag
{
  float font_size;
  NSFont *controlFont;

  isSmallControlSize = flag;

  if (isSmallControlSize)
    {
      font_size = [NSFont smallSystemFontSize];
      [unitPopUpCell setControlSize: NSSmallControlSize];
      [selectionPopUpCell setControlSize: NSSmallControlSize];
    }
  else
    {
      font_size = [NSFont systemFontSize];
      [unitPopUpCell setControlSize: NSRegularControlSize];
      [selectionPopUpCell setControlSize: NSRegularControlSize];
    }

  controlFont = [NSFont controlContentFontOfSize: font_size];
  [textField setFont: controlFont];
  [toField setFont: controlFont];
  [toTextFieldCell setFont: controlFont];
  [unitPopUpCell setFont: controlFont];
  [selectionPopUpCell setFont: controlFont];
}

- (BOOL) isSmallControlSize
{
  return isSmallControlSize;
}

- (BOOL) isFlipped
{
  return YES;
}

@end
