/* X/Motif WidgetSet category implementation of  Cell class
 *
 * Copyright (C)  1994, 1995  The Board of Trustees of  
 * The Leland Stanford Junior University.  All Rights Reserved.
 *
 * Authors: Scott Francis, Fred Harris, Paul Kunz,
 *          Imran Qureshi, and Libing Wang
 * At: Stanford Linear Accelerator Center, Stanford University and
 *     University of Hawaii
 *
 * This file is part of an Objective-C class library for X/Motif
 *
 * xmCell.m,v 1.17 1995/04/22 23:12:37 pfkeb Exp
 */

#include "Cell.h"
#include "xtCell.h"

#include <stdlib.h>
#include "Motif.h"
#include <Xm/PushB.h>
#define Window X11Window
#include <X11/IntrinsicP.h>
#undef Window
#include "Application.h"
#include "Control.h"

extern char *xtCellInstanceName(void);

char *CellInstanceName(void)
{
    return xtCellInstanceName();
}

/* Private methods of Motif interface */

@implementation Cell(WidgetSet)

- _setFont
{
    char	*fontName = "-adobe-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*";
    XFontStruct	*font;
    XmFontList	fontList;
    Display	*disp = [NXApp _X_display];
    Pixel	black;

    font = XLoadQueryFont( disp, fontName );
    fontList = XmFontListCreate( font, XmSTRING_DEFAULT_CHARSET );
    black = XBlackPixel(disp, XDefaultScreen(disp));

    [self _setArg:XmNfontList to:(XtArgVal)fontList];
    [self _setArg:XmNforeground to:black];
    return self;
}

- _moveTo:(NXCoord)x :(NXCoord)y
{
    XtMoveWidget(widgetid, x, y);
    return self;
}

- _setEnabled:(BOOL)flag
{
    [self _setArg:XmNsensitive to:flag];
    return self;
}

- _setAdjustedFrame:(const NXRect *)aFrame
{
    NXRect	rect;
    NXSize	size;

    rect = *aFrame;
    [self _getSizeAdjust:&size];
    rect.size.width  += size.width;
    rect.size.height += size.height;
    [self _setArg:XmNx      to:rect.origin.x];
    [self _setArg:XmNy      to:rect.origin.y];
    [self _setArg:XmNwidth  to:rect.size.width];
    [self _setArg:XmNheight to:rect.size.height];
    return self;
}

- _setFrame:(const NXRect *)frame inView:(Control *)aView
{
    controlView = aView;
    if ( !frame ) 
	return self;
    _frame = *frame;
    if ( controlView ) {
	NXRect  vrect, xframe;

	[controlView getFrame:&vrect];
	xframe = _frame;
	xframe.origin.y = vrect.size.height 
			  - _frame.size.height - _frame.origin.y;
	[self _setAdjustedFrame:&xframe];
    } else {
	fprintf(stderr, "Cell error: no controlView to set frame\n");
    }
    return self;
}

- _setSize:(const NXSize *)size
{
    _frame.size = *size;
    [self _setArg:XmNwidth  to:_frame.size.width];
    [self _setArg:XmNheight to:_frame.size.height];
    [self _setArg:XmNrecomputeSize to:False];
    return self;
}

- _getSizeAdjust:(NXSize *)size
{
  /* Any cell that needs its control View to increase its size 
   * should override this method and return the size adjustment
   */
    if ( size ) {
	size->width  = 0;
	size->height = 0;
    }
    return self;
}

- _getFrame:(NXRect *)frame
{
    [self _getArg:XmNx 	    into:(XtArgVal *)&frame->origin.x];
    [self _getArg:XmNy	    into:(XtArgVal *)&frame->origin.y];
    [self _getArg:XmNwidth  into:(XtArgVal *)&frame->size.width];
    [self _getArg:XmNheight into:(XtArgVal *)&frame->size.height];
    if ( controlView) {
	NXRect rect;
	[controlView getFrame:&rect];
	frame->origin.y 
	    = rect.size.height - frame->origin.y - frame->size.height; 
    } else {
	fprintf(stderr, "Cell error: no controlView to compute frame\n");
    }
    return self;
}

- _addCallback
{
    return self;
}

- _managedBy:parent
{
    Widget widparent;

    if (!(widparent = [parent _widget]))
        if ( ![parent respondsTo:@selector(superview)] ||
              !(widparent = 
	         [[parent perform:@selector(superview)] _widget] ) ) {
            fprintf(stderr, "Cell: parent widget not found\n");
            return 0;
        }
    [self _managedBy:parent wid:widparent];

    return self;
}    

- _managedBy:parent wid:(void *)widget;
{
    if (!classname) {
        fprintf(stderr, "Cell classname unknown\n");
    }
    if (widgetid) {
        XtManageChild(widgetid);
    } else {
	if ( !contents ) {
	  /* if no contents yet, then make default */
//	    [self setStringValue:" "];
/* I don't think that the initial value should be set to a <space>.
   People will click in the uninitialized
   cell and type something in.  The cursor will be placed after the <space>,
   and the entry will then have a <space> prepended.  This is nasty for
   filenames! E.g. " temp.tmp" is a badly formed filename.
   */
	    [self setStringValue:""];
	}
	[self _setFont];
	widgetid = XtCreateManagedWidget(instancename, classname,
				     widget, arglist, numargs);
	[self _addCallback];
    }	
    parentid = parent;
    return self;
}

- _destroy
{
    if ( widgetid ) {
        XtDestroyWidget(widgetid);
    }
    widgetid = NULL;
    return self;
}    
- (void *)_widget
{
    return widgetid;
}

- _copy
{
  /* On entry, receiving Cell has copy of pointers to objects from
   * another cell.   These must be cleared so new objects can be 
   * created
   */
    allocedargs = numargs = 0;
    arglist = NULL;
    widgetid = NULL;
    return self;
}
@end
