/* Implementation of  Control class
 *
 * Copyright (C)  1993, 1994, 1995  The Board of Trustees of  
 * The Leland Stanford Junior University.  All Rights Reserved.
 *
 * Authors: Scott Francis, Paul Kunz, Tom Pavel, Imran Qureshi, and Libing Wang
 *
 * This file is part of an Objective-C class library for a window system.
 *
 * Control.m,v 1.63 1995/12/13 22:32:58 fedor Exp
 */

#include "Control.h"

#include "ActionCell.h"
#include "Application.h"

extern char *ControlInstanceName(void);

@interface View(WidgetSet)
- _managedBy:parent wid:(void *)widget;
- _destroy;
@end

@implementation Control:View

+ setCellClass:factoryId
{
  return [self notImplemented:_cmd];
}

- initFrame:(const NXRect *)frameRect
{
    [super initFrame:frameRect];
    instancename = ControlInstanceName();
    return self;
}

- moveTo:(NXCoord)x :(NXCoord)y
{
    frame.origin.x = x;
    frame.origin.y = y;
    bounds.origin.x = x;
    bounds.origin.y = y;
    /* assume that widget will be moved by the cell class 
     */
    if ( cell != 0 ) {
	[cell _moveTo:x :y];
    } else {
    	[super moveTo:x :y];
    }
    return self;
}

- free
{
  /* Note that cell needs to be destroyed here, before it is freed. - fedor */
    [cell _destroy];
    [cell free];
    cell = nil;
    return [super free];
}

- sizeToFit
{
  return [self notImplemented:_cmd];
}

- sizeTo:(NXCoord)width :(NXCoord)height
{
  return [self notImplemented:_cmd];
}

- calcSize
{
  return [self notImplemented:_cmd];
}

- cell
{
    return cell;
}

- setCell:aCell
{
  Cell *old = cell;
  cell = aCell;
  return old;
}

- selectedCell
{
    return cell;
}

- target
{
    return [cell target];
}

- setTarget:anObject
{
    [cell setTarget:anObject];
    return self;
}

- (SEL)action
{
    return [cell action];
}

- setAction:(SEL)aSelector
{
    [cell setAction:aSelector];
    return self;
}

- (int)tag
{
    return [cell tag];
}

- setTag:(int)anInt
{
    return [cell setTag:anInt];
}

- (int)selectedTag
{
 /*
  * Matrix doesn't doesn't implement this method, thus we implement it here
  * in way that it will work for Matrix. 
  */
    return [[self selectedCell] tag];
}

- ignoreMultiClick:(BOOL)flag
{
  return [self notImplemented:_cmd];
}

- mouseDown:(NXEvent *)theEvent
{
  return [self notImplemented:_cmd];
}

- (int)mouseDownFlags
{
  [self notImplemented:_cmd];
  return 0;
}

- (int)sendActionOn:(int)mask
{
  [self notImplemented:_cmd];
  return 0;
}

- (BOOL)isContinuous
{
    return [cell isContinuous];
}

- setContinuous:(BOOL)flag
{
    [cell setContinuous: flag];
    return self;
}

- (BOOL)isEnabled
{
    return [cell isEnabled];
}

- setEnabled:(BOOL)flag
{
    [cell setEnabled:flag];
    return self;
}

- setFloatingPointFormat:(BOOL)autoRange left:(unsigned)leftDigits 
                                       right:(unsigned)rightDigits
{
  return [self notImplemented:_cmd];
}


- (int) alignment
{
    return [cell alignment];
}

- setAlignment:(int)mode
{
    [cell setAlignment:mode];
    return self;
}

- font
{
  return [self notImplemented:_cmd];
}

- setFont:fontObj
{
  [cell setFont: fontObj];
  return self;
}

- setStringValue:(const char *)aString
{
    [cell setStringValue:aString];
    return self;
}

- setStringValueNoCopy:(const char *)aString
{
  return [self notImplemented:_cmd];
}

- setStringValueNoCopy:(char *)aString shouldFree:(BOOL)flag
{
  return [self notImplemented:_cmd];
}

- setIntValue:(int)anInt
{
    [cell setIntValue:anInt];
    return self;
}

- setFloatValue:(float)aFloat
{
    [cell setFloatValue:aFloat];
    return self;
}

- setDoubleValue:(double)aDouble
{
    [cell setDoubleValue:aDouble];
    return self;
}

- (const char *)stringValue
{
    return [cell stringValue];
}

- (int)intValue
{
    return [cell intValue];
}

- (float)floatValue
{
    return [cell floatValue];
}

- (double)doubleValue
{
    return [cell doubleValue];
}

- update
{
  return self;
}

- updateCell:aCell
{
  return [self notImplemented:_cmd];
}

- updateCellInside:aCell
{
  return [self notImplemented:_cmd];
}

- drawCellInside:aCell
{
  return [self notImplemented:_cmd];
}

- drawCell:aCell
{
  return [self notImplemented:_cmd];
}

- selectCell:aCell
{
    return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
{
  /* FIXME: Implement */
  return self;
}

- sendAction:(SEL)theAction to:theTarget
{
    if ( !theAction ) {
        return nil;	// a guess, documentation not clear
    }
    if ( [NXApp sendAction:theAction to:theTarget from:self] ) {
        return self;
    }
    return nil;
}

- takeIntValueFrom:sender
{
    [cell setIntValue:[sender intValue]];
    return self;
}

- takeFloatValueFrom:sender
{
    [cell setFloatValue:[sender floatValue]];
    return self;
}

- takeDoubleValueFrom:sender
{
    [cell setDoubleValue:[sender doubleValue]];
    return self;
}

- takeStringValueFrom:sender
{
    [cell setStringValue:[sender stringValue]];
    return self;
}

- currentEditor
{
  return [self notImplemented:_cmd];
}

- abortEditing
{
    return self;
}

- validateEditing
{
  return [self notImplemented:_cmd];
}

- resetCursorRects
{
  return [self notImplemented:_cmd];
}

- write:(NXTypedStream *)stream
{
    [super write:stream];
    objc_write_object(stream,cell);
    return self;
}

- read:(TypedStream*)typedStream
{
    [super read:typedStream];
    objc_read_object(typedStream,&cell);
    instancename = ControlInstanceName();
    return self;
}

+ newFrame:(const NXRect *)frameRect
{
    return [[super alloc] initFrame:frameRect];
}


/* Methods not in NeXTSTEP */

- sendAction
{
    if ( cell && [cell action] ) {
        if ( [cell target] ) {
	    [[cell target] perform:[cell action] with:self];
	} 
    }
    return self;
}

- setFrame:(const NXRect *)frameRect
{
  /* Not in OpenStep Control class */
    [super setFrame:frameRect];
    [cell _setFrame:frameRect inView:self];
    return self;
}

- setIcon:(const char *)iconName
{
    return [cell setIcon:iconName];
}

- _managedBy:parent wid:(void*)widget
{
    [super _managedBy:parent wid:widget];
    if ( cell ) {
	NXRect	rect = frame;
	rect.origin.x = 0;
	rect.origin.y = 0;
    	[cell _setFrame:&rect inView:self];
	[cell _managedBy:self];
    }
    return self;
}
- _destroy
{
    if ( cell ) {
	[cell _destroy];
    } else { 
    	[super _destroy];
    }
    return self;
}

@end
