/*---------------------------------------------------------------------------
Specify.m -- Copyright (c) 1991 Rex Pruess
  
   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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA, or send
   electronic mail to the the author.
  
When the user selects the "specific" radio button, this code comes to life.
It creates a window with a scrollview containing the switches for every
field available to the user.
  
Rex Pruess <Rex-Pruess@uiowa.edu>
  
$Header: /rpruess/apps/Ph/query.subproj/RCS/Specify.m,v 2.0 91/11/19 08:22:43 rpruess Exp $
-----------------------------------------------------------------------------
$Log:	Specify.m,v $
Revision 2.0  91/11/19  08:22:43  rpruess
Revision 2.0 is the initial production release of Ph.

-----------------------------------------------------------------------------*/

#define CELLSEP 2.0		/* Separator pixels between cell rows */
#define CELLWIDTH 160.0		/* Cell width */
#define CELLHEIGHT 15.0		/* Cell height */

#define BETWEENCOLWIDTH 4.0	/* Pixels between the two columns */
#define SCROLLERWIDTH 22.0	/* Width of the scroller */

#define LEFTMARGIN 12.0		/* Reserve border space for asethics */
#define RIGHTMARGIN 1.0
#define TOPMARGIN 6.0

#define TITLEHEIGHT 16.0	/* Height of the title bar */

/* Standard C header files */
#include <stdio.h>
#include <strings.h>
//#include <sys/malloc.h>

/* Objective-C & Appkit header files */
#import <objc/Object.h>
#import <objc/List.h>

#import <appkit/Application.h>
#import <appkit/Button.h>
#import <appkit/ButtonCell.h>
#import <appkit/ScrollView.h>
#import <appkit/Text.h>

/* Application class header file */
#import "Specify.h"
#import "Query.h"
#import "../PhShare.h"

@implementation Specify

/*---------------------------------------------------------------------------
Initialization: A window is created just large enough to hold all of the
switches, provided it is no more than 1/2 the screen height.  A scroll view
consumes the entire window.  A two column matrix of switches is assigned
to the scroll view's docview.  There is one switch for each "field".
-----------------------------------------------------------------------------*/
- initSpecify:(int)nItems x:(float)locX y:(float)locY title:(const char *)aTitle
{
   int             nRows;
   float           winHeight;
   float           winWidth;
   NXSize          screenSize;
   NXRect          winRect;

   [NXApp getScreenSize:&screenSize];

   /*** Create the window to hold the switches. */

   nRows = (nItems + 1) / 2;
   winHeight = TOPMARGIN + ((CELLHEIGHT + CELLSEP) * nRows);

   if (winHeight > screenSize.height / 2.0)
      winHeight = screenSize.height / 2.0;

   winWidth = SCROLLERWIDTH + CELLWIDTH * 2.0 + LEFTMARGIN + RIGHTMARGIN + BETWEENCOLWIDTH;

   NXSetRect (&winRect, locX, locY - winHeight - TITLEHEIGHT, winWidth, winHeight);

   specWin = [[Window alloc] initContent:&winRect
      style:NX_TITLEDSTYLE
      backing:NX_BUFFERED
      buttonMask:(NX_CLOSEBUTTONMASK)
      defer :NO];

   [specWin setBackgroundGray:NX_LTGRAY];
   [specWin setFreeWhenClosed:NO];
   [specWin setDelegate:self];

   [specWin setTitle:aTitle];

   /*** Create the scrollview & its document view. */

   [self createViews:winWidth :winHeight];

   [specWin display];

   /*** Initialize the starting location for the first cell. */

   NXSetRect (&cellRect, LEFTMARGIN, TOPMARGIN, CELLWIDTH, CELLHEIGHT);

   /*** Set initial sizes of the view.  This grows as switches are added. */

   viewSize.height = TOPMARGIN;
   viewSize.width = winWidth;

   return self;
}

/*---------------------------------------------------------------------------
Crete the scrollview and its document view.  Add them as subviews to the
window's content view.
-----------------------------------------------------------------------------*/
- createViews:(float)width :(float)height
{
   id              docView;
   NXRect          vRect;

   NXSetRect (&vRect, 0.0, 0.0, width, height);

   sView = [[ScrollView alloc] initFrame:&vRect];
   [sView setVertScrollerRequired:YES];
   [sView setHorizScrollerRequired:NO];
   [sView setBorderType:NX_NOBORDER];
   [sView setAutosizing:NX_HEIGHTSIZABLE];
   [sView setBackgroundGray:NX_LTGRAY];

   docView = [[View alloc] initFrame:&vRect];
   [docView setAutosizing:NX_HEIGHTSIZABLE];
   [docView setFlipped:YES];

   [sView setDocView:docView];

   [[specWin contentView] addSubview:sView];
   [[sView superview] setAutoresizeSubviews:YES];

   return self;
}

/*---------------------------------------------------------------------------
Each row can hold two switches.  If a new row is created, grow the document
view so scrolling will behave.
-----------------------------------------------------------------------------*/
- addSwitch:(const char *)aName
{
   NXRect          aRect;
   id              aButton;

   aButton = [[Button alloc] initFrame:&cellRect
      title:aName
      tag:0
      target:nil action:NULL key:0 enabled:YES];

   [aButton setType:NX_SWITCH];
   [aButton setIconPosition:NX_ICONLEFT];
   [aButton setAlignment:NX_LEFTALIGNED];

   [[sView docView] addSubview:aButton];

   if (cellRect.origin.x == LEFTMARGIN) {
      cellRect.origin.x = LEFTMARGIN + CELLWIDTH + BETWEENCOLWIDTH;

      [[sView docView] getFrame:&aRect];

      viewSize.height += CELLHEIGHT + CELLSEP;
      [[sView docView] sizeTo:aRect.size.width:viewSize.height];
   }
   else {
      cellRect.origin.x = LEFTMARGIN;
      cellRect.origin.y = viewSize.height;
   }

   return self;
}

/*---------------------------------------------------------------------------
Pass through all the switches and figure out which ones have been selected.
-----------------------------------------------------------------------------*/
- getSelectedFields:(char *)theFields
{
   int             i;
   id              anObject;
   id              subviewList;

   *theFields = '\0';

   subviewList = [[sView docView] subviews];

   for (i = 0; i < [subviewList count]; i++) {
      anObject = [subviewList objectAt:i];

      if ([anObject isKindOf:[Button class]] == YES && [anObject intValue] == 1) {

	 if (strlen (theFields) + strlen ([anObject title]) + 2 > COMSIZE) {
	    fprintf (stderr, "%s: Too many Return Fields requested.  Some ignored.\n",[NXApp name]);
	    break;
	 }

	 strcat (theFields, " ");
	 strcat (theFields,[anObject title]);
      }

   }

   return self;
}

/*---------------------------------------------------------------------------
After all the switches have been created, the view must receive a display
message.  The caller had better do this!
-----------------------------------------------------------------------------*/
- updateDisplay:sender
{
   [[sView superview] display];
   return self;
}

/*---------------------------------------------------------------------------
Order the window out of here.
-----------------------------------------------------------------------------*/
- orderWindowOut:sender
{
   [specWin orderOut:self];
   return self;
}

/*---------------------------------------------------------------------------
Show the window and make it key.
-----------------------------------------------------------------------------*/
- showWindow:sender
{
   [specWin makeKeyAndOrderFront:self];
   return self;
}

/*---------------------------------------------------------------------------
The window can grow veritcally, but not horizontally.
-----------------------------------------------------------------------------*/
- windowWillResize:sender toSize:(NXSize *) frameSize
{
   NXRect          wRect;

   [sender getFrame:&wRect];
   frameSize -> width = wRect.size.width;

   return self;
}

@end
