/* Implementation of Menu class
 *
 * Copyright (C)  1993  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 (SLAC)
 *	    Mike Kienenberger (Alaska)
 *
 * This file is part of an Objective-C class library a window system
 *
 * Menu.m,v 1.47 1995/12/13 22:33:06 fedor Exp
 *
 */

#include "Menu.h"

/* Required for implementation: */
#include "MenuCell.h"
#include "Application.h"
#include "Matrix.h"
#include <objc/List.h>

extern char *MenuInstanceName(void);

static NSZone *menuZone = NS_NOZONE;

@implementation Menu:Panel

+ setMenuZone:(NSZone *)aZone
{
    menuZone = aZone;
    return self;
}

+ (NSZone *)menuZone
{
    menuZone = NSCreateZone(vm_page_size,vm_page_size,YES);
    NSNameZone(menuZone,"Menus");

    return menuZone;
}

+ alloc
{
    return [super allocFromZone:menuZone];
}


- init
{
    return [self initTitle:"Menu"];
}

- initTitle:(const char *)aTitle
{
    NXRect	frameRect = {{0,0}, {0,0}};
    
//    [super init];  /* We don't want Window's init method */
    [self _init];
    instancename = MenuInstanceName();
    [self setTitle:aTitle];
    matrix = [[Matrix alloc] initFrame:&frameRect mode:NX_TRACKMODE
                             cellClass:[MenuCell class] numRows:0 numCols:1];
    autoUpdate = NO;
    return self;
}

- addItem:(const char *)aString action:(SEL)aSelector 
                         keyEquivalent:(unsigned short)charCode
{
    MenuCell	*cell;
    
    [matrix addRow];
    cell = [[matrix cellList] lastObject];
    [cell setStringValue:aString];
    [cell setAction:aSelector];
    [cell setTarget:nil];
    [cell setKeyEquivalent:charCode];
    return self;
}

- addItem:(const char*)aString action:anObject sel:(SEL)aSelector
{
    MenuCell	*cell;
    List	*cellList = [matrix cellList];
    
    [matrix addRow];
    cell = [cellList lastObject];
    [cell setStringValue:aString];
    [cell setTarget:anObject];
    [cell setAction:aSelector];
    [cell _setControlView:matrix];
    return cell;
}

- setSubmenu: aMenu forItem: aCell
{
    List	*cellList = [matrix cellList];

    [matrix addRow];
    [aCell setSubmenu:aMenu];
    [cellList replaceObject: [cellList lastObject] with: aCell];
    return aCell;
}

- itemList
{
    return matrix;
}

- setItemList: aMatrix
{
  id old = matrix;
  matrix = aMatrix;
  return old;
}

- display
{
    return self;
}

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

- moveTopLeftTo: (NXCoord)x : (NXCoord)y
{
    return [self notImplemented: _cmd];
}

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

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

- free
{
    [matrix free];
    return [super free];
}

- setSubmenu: aMenu forItemName: (const char*)aString
{
    MenuCell	*cell;
    List	*cellList = [matrix cellList];

    [matrix addRow];
    cell = [cellList lastObject];
    [cell setStringValue:aString];
    [cell setSubmenu:aMenu];
    return cell;
}

- setHelpSubmenu:aMenu
{
    MenuCell	*cell = [self setSubmenu:aMenu forItemName:"Help"];

    _helpSubmenu = cell;
    return cell;
}


- setAutoupdate:(BOOL)flag
{
    autoUpdate = flag;
    return self;
}

/* Update isn't quite finished... but here's a first brush at it.
 	Tried to emulate the NeXT docs here...:
	if autoUpdate is on, checks each item for an update action.
	If they have the action, then figure out which, delegate, NXApp
	or [NXApp delegate] has the means for responding to the updateacton.
 */

- update
{
    List	*cellList = [matrix cellList];
//  SEL		action;
    int		i,count;
    
    if (autoUpdate) {
        count = [cellList count];
	for (i=0; i < count; i++)
	{
//	    if ( (action = [[cellList objectAt:i] updateAction]) )
//	    {
//	    	if (((delegate) && ([delegate respondsTo:action])) &&
//		    ([delegate perform:action with:[cellList objectAt:i]]))
//		    	[[cellList objectAt:i <<method to draw goes here>>] ;
//			;
//		else if (([NXApp respondsTo:action]) &&
//		    [NXApp perform:action with:[cellList objectAt:i]])
//		        [[cellList objectAt:i ];
//			;
//		else if (([NXApp delegate] && 
//		    [[NXApp delegate] respondsTo:action]) &&
//		    [[NXApp delegate] perform:action 
//		                         with:[cellList objectAt:i]])
//		        [[cellList objecAt:i ];
//			;
//	    }
	}
    }
    return self;
}

- findCellWithTag: (int)aTag
{
    return [self notImplemented: _cmd];
}

- getLocation: (NXPoint *)theLocation forSubmenu: aSubmenu
{
    return [self notImplemented: _cmd];
}

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

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



- (BOOL)_isMain
/*
	Returns YES if this is the applications main menu.
 */
{
    return self == [NXApp mainMenu];
}

- _managedBy:parent
{
    void	*widget = [parent _widget];

    if (!widget) {
    	fprintf(stderr, "Menu: parent widget not found\n");
	return nil;
	}

    return [self _managedBy:parent wid:widget];
}

- write: (NXTypedStream *)typedStream
{
  return [self notImplemented:_cmd];
}

- read: (NXTypedStream *)typedStream
{
 /*
  * Since we'll not use the Window of the menu, the buck stops
  * here for archiving, i.e. no [super read:stream]; 
  */
#ifdef DEBUG
    fprintf(stderr, "reading Menu\n");
#endif
    objc_read_object(typedStream, &matrix);

    return self;
}

- awake
{
 /*
  * Since we'll not use the Window of the menu, we don't want to
  * invoke Window's awake method  
  */
    [self _init];
    instancename = MenuInstanceName();
    
    /* should be removed later when these are archived */
    [self setTitle:"Menu"];
    autoUpdate = NO;

    return self;
}

- awakeFromNib
{
 /*
  * Since we'll not use the Window of the menu, we don't want to
  * invoke Window's awake method  
  */

    return self;
}

@end
