/*****************************************************************************/
// FileQueue.m
// implementation file of FileQueue class of ViewGif2 application
// January 1990  Carl F. Sutter
// FileQueue is a generic IB module that keeps a queue of strings that can be
// returned on demand by a controlling object.  It can display a panel
// that lets the user control the order etc. of the queue.  Most of the
// controls are set up in the IB, making customization easy.
/*****************************************************************************/

#import "FileQueue.h"
#import <appkit/Application.h>
#import <appkit/Window.h>
#import <appkit/TextField.h>
#import <appkit/Matrix.h>
#import <appkit/publicWraps.h>		// for NXBeep
#import <sys/param.h>			// for MAXPATHLEN
#import <string.h>			// for strcpy

@implementation FileQueue

/*****************************************************************************/
/* new - factory method							     */
/*****************************************************************************/
+ new
   {
   self = [super new];
   [self setup];
   return( self );
   } /* new 1/22/90 CFS */


/*****************************************************************************/
/* new - factory method	with target and action				     */
/*****************************************************************************/
+ new:(id )targ action:(SEL )act 
   {
   self = [super new];
   [self setup];
   target = targ;
   action = act;
   return( self );
   } /* new:action: 1/23/90 CFS */
  

/*****************************************************************************/
/* setup - initialize instance variables and panel etc.  		     */
/*****************************************************************************/
- setup
   {
   NXSize	nxsList;
   NXSize	nxsCell;
   
   /* load nib defining panel and outlets */
   [NXApp loadNibSection:"FileQueue.nib" owner:self];

   /* set attributes for the scrollview and matrix */
   [queueScroll setVertScrollerRequired:YES];
   [queueScroll setBorderType:NX_BEZEL];
   [queueScroll getContentSize:&nxsList];
   [queueMatrix getCellSize:&nxsCell];
   nxsCell.width = nxsList.width;
   [queueMatrix setCellSize:&nxsCell];
   [queueMatrix setAutoscroll:YES];
   
   /* attach the matrix to the scrollview */
   [queueScroll setDocView:queueMatrix];
   
   /* remove any matrix cells drawn in the IB */
   while ([queueMatrix cellCount]) [queueMatrix removeRowAt:0 andFree:YES];
   [queueMatrix sizeToCells];
   
   /* init instance variables */
   nNumRows = 0;
   bPaused = NO;
   bSendWhenReady = NO;
   
   return( self );
   } /* setup 1/23/90 CFS */
  

/*****************************************************************************/
/* outlet initialization methods   					     */
/*****************************************************************************/
- setQueuePanel:anObject   { queuePanel  = anObject;  return( self ); }
- setQueueScroll:anObject  { queueScroll = anObject;  return( self ); }
- setQueueMatrix:anObject  { queueMatrix = anObject;  return( self ); }


/***************************************************************************/
/* windowWillResize - Delegate message sent from main window.		   */
/* Prevent window from getting too small.				   */
/***************************************************************************/
- windowWillResize:sender toSize:(NXSize *)frameSize
   {
   /* minimum size to allow for the buttons and a small scrollview */
   frameSize->width  = MAX( 250, frameSize->width );
   frameSize->height = MAX( 150, frameSize->height );
   return( self );
   } /* windowWillResize 9/14/89 CFS */
   

/*****************************************************************************/
/* show - display the queue panel					     */
/*****************************************************************************/
- show:sender
   {
   [queuePanel makeKeyAndOrderFront:self];
   return( self );
   } /* show 1/22/90 CFS */

   
/*****************************************************************************/
/* pause - pause the queue						     */
/*****************************************************************************/
- pause:sender
   {
   bPaused = !bPaused;
   if (!bPaused && bSendWhenReady) [self sendNext];
   return( self );
   } /* pause 1/22/90 CFS */


/*****************************************************************************/
/* remove - remove highlighted cells   					     */
/*****************************************************************************/
- remove:sender
   {
   int  i;
 
   /* enumerate the highlighted cells */
   nNumSelected = 0;
   [queueMatrix sendAction:@selector(countOneSelected:) to:self forAllCells:NO];
   /* delete the selected cells */
   for (i=0; i<nNumSelected; i++)
      {
      [queueMatrix removeRowAt:(nSelectedRows[i]-i) andFree:YES];
      nNumRows--;
      }
   [queueMatrix sizeToCells];
   [queueScroll display];
   return( self );
   } /* remove 1/18/90 CFS */


/*****************************************************************************/
/* toTop - move selected cells to the top of the queue			     */
/*****************************************************************************/
- toTop:sender
   {
   int  nRealRow, i;
   
   /* enumerate the highlighted cells */
   nNumSelected = 0;
   [queueMatrix sendAction:@selector(countOneSelected:) to:self forAllCells:NO];
   /* move the selected cells to the top */
   for (i=nNumSelected-1; i>=0; i--)
      {
      [queueMatrix insertRowAt:0];
      nRealRow = nSelectedRows[i] + nNumSelected - i;
      [[queueMatrix cellAt:0 :0] setStringValue:
         [[queueMatrix cellAt:nRealRow :0] stringValue]];
      [queueMatrix removeRowAt:nRealRow andFree:YES];
      }
   [queueMatrix sizeToCells];
   [queueScroll display];
   return( self );
   } /* toTop 1/18/90 CFS */


/*****************************************************************************/
/* toBottom - move selected cells to the bottom of the queue		     */
/*****************************************************************************/
- toBottom:sender
   {
   int  nRealRow, i;
   
   /* enumerate the highlighted cells */
   nNumSelected = 0;
   [queueMatrix sendAction:@selector(countOneSelected:) to:self forAllCells:NO];
   /* move the selected cells to the bottom */
   for (i=0; i<nNumSelected; i++)
      {
      [queueMatrix addRow];
      nRealRow = nSelectedRows[i] - i;
      [[queueMatrix cellAt:nNumRows :0] setStringValue:
         [[queueMatrix cellAt:nRealRow :0] stringValue]];
      [queueMatrix removeRowAt:nRealRow andFree:YES];
      }
   [queueMatrix sizeToCells];
   [queueScroll display];
   return( self );
   } /* toBottom 1/18/90 CFS */


/*****************************************************************************/
/* countOneSelected - enumerates one cell, adds row to the selected list     */
/*****************************************************************************/
- (BOOL)countOneSelected:cell
   {
   int	nRow, nCol;
   
   [queueMatrix getRow:&nRow andCol:&nCol ofCell:cell];
   nSelectedRows[nNumSelected] = nRow;
   nNumSelected++;
   if (nNumSelected == MAXSELECTABLE) return( NO );
   return( YES );  // to continue to next highlighted cell
   } /* countOneSelected 1/18/90 CFS */
   

/*****************************************************************************/
/* setTarget - sets the object to return queue items to 		     */
/*****************************************************************************/
- setTarget:(id)targ
   {
   target = targ;
   return( self );
   } /* setTarget 1/22/90 CFS */


/*****************************************************************************/
/* setAction - sets the method that will be called with the new item        */
/* there will be one parameter - a pointer to a standard C string	     */
/*****************************************************************************/
- setAction:(SEL)aSelector
   {
   action = aSelector;
   return( self );
   } /* setAction 1/22/90 CFS */


/*****************************************************************************/
/* addItem - adds one string to the bottom of the queue			     */
/*****************************************************************************/
- (BOOL)addItem:(const char *)szFileName
   {
   [queueMatrix addRow];
   [queueMatrix sizeToCells];
   [[queueMatrix cellAt:nNumRows :0] setStringValue:szFileName];
   [queueScroll display];
   nNumRows++;
   if (!bPaused && bSendWhenReady) [self sendNext];
   return( YES );
   } /* addItem 1/22/90 CFS */


/*****************************************************************************/
/* retrieveNext - immediately return the next string on the queue	     */
/* disregards the pause button - use retrieveNextWhenReady for that function */
/*****************************************************************************/
- (char *)retrieveNext
   {
   char szReturn[MAXPATHLEN + 1];
   
   if (nNumRows == 0) return( NULL );
   strcpy( szReturn , [[queueMatrix cellAt:0 :0] stringValue] );
   [queueMatrix removeRowAt:0 andFree:YES];
   [queueMatrix sizeToCells];
   [queueScroll display];
   nNumRows--;
   return( szReturn );
   } /* retrieveNext 1/22/90 CFS */
   
   
/*****************************************************************************/
/* retrieveNextWhenReady - send the next queue item when it is available     */
/*****************************************************************************/
- retrieveNextWhenReady
   {
   bSendWhenReady = YES;
   if (!bPaused) [self sendNext];
   return( self );
   } /* retrieveNextWhenReady 1/22/90 CFS */
   
   
/*****************************************************************************/
/* sendNext - send the next queue item to the target object		     */
/*****************************************************************************/
- sendNext
   {
   char szReturn[MAXPATHLEN + 1];
   
   if (nNumRows > 0)
      {
      strcpy( szReturn, [self retrieveNext] );
      [target perform:action with:(id)szReturn];
      bSendWhenReady = NO;
      }
   return( self );
   } /* sendNext 1/22/90 CFS */


@end
