/***************************************************************************/
/* ViewBitmap.m - implementation file to ViewBitmap class		   */
/* Takes a bitmap, and displays it in a window with scrollers.             */
/* The bitmap can be saved as a TIFF file, and another object (such as an  */
/* activate menu) can be notified if the window is closed.		   */
/* January 1990   Carl F. Sutter					   */
/***************************************************************************/

#import "ViewBitmap.h"
#import <appkit/Window.h>
#import <appkit/ScrollView.h>
#import <appkit/Application.h>	 // for NXApp
#import <appkit/Panel.h>	 // for NXRunAlertPanel
#import <string.h>		 // for strcpy, strcat
#import <stdlib.h>		 // for MIN
#import <libc.h>		 // for file i/o

@implementation ViewBitmap

/***************************************************************************/
/* newBitmap - show the bitmap in a new window				   */
/***************************************************************************/
+ newBitmap:(Bitmap *)bmpIn
   {
   NXRect nxrBitmap;
   
   [bmpIn getSize:&(nxrBitmap.size)];
   self = [super newFrame:&nxrBitmap];
   bmpImage = bmpIn;
   nxsBitmap = nxrBitmap.size;
   strcpy( szTitle, "" );
   nxpTopLeft.x = nxpTopLeft.y = 100.0;
   [self setup];
   return( self );
   } /* newBitmap 1/23/90 CFS */
   
   
/***************************************************************************/
/* newBitmap:title - show the bitmap in a new window with the given title  */
/***************************************************************************/
+ newBitmap:(Bitmap *)bmpIn title:(char *)szTitleIn
   {
   NXRect nxrBitmap;
   
   [bmpIn getSize:&(nxrBitmap.size)];
   self = [super newFrame:&nxrBitmap];
   bmpImage = bmpIn;
   nxsBitmap = nxrBitmap.size;
   strcpy( szTitle, szTitleIn );
   nxpTopLeft.x = nxpTopLeft.y = 100.0;
   [self setup];
   return( self );
   } /* newBitmap:title 1/23/90 CFS */
   
   
/***************************************************************************/
/* newBitmap:title:topLeft: - display bitmap with given position and title  */
/***************************************************************************/
+ newBitmap:(Bitmap *)bmpIn title:(char *)szTitleIn topLeft:(NXPoint)nxpTopLeftIn
   {
   NXRect nxrBitmap;
   
   [bmpIn getSize:&(nxrBitmap.size)];
   self = [super newFrame:&nxrBitmap];
   bmpImage = bmpIn;
   nxsBitmap = nxrBitmap.size;
   strcpy( szTitle, szTitleIn );
   nxpTopLeft = nxpTopLeftIn;
   [self setup];
   return( self );
   } /* newBitmap:title:topLeft: 1/23/90 CFS */


/***************************************************************************/
/* setup - make a new scrolling view with the bitmap and title	           */
/* the bitmap is not copied, so the sender should not free the bitmap that */
/* is sent!  The origin id for the top-left of the window, since the top   */
/* shouldn't be pushed off the screen.                                     */
/***************************************************************************/
- setup
   {
   ScrollView	*scrollView;	/* scroll view to hold bitmap     */
   Window	*win;		/* window to hold ScrollView      */
   NXRect	nxrView;	/* bounds of this view            */
   NXRect	nxrScrollView;  /* bounds of enclosing ScrollView */
   NXRect	nxrWinHeight;	/* bounds of enclosing window     */
   NXSize	nxsScreen;	/* size of screen		  */
      
   /* make the ScrollView, and put the View in it */
   nxrView.origin.x = nxrView.origin.y = 0.0;	
   nxrView.size = nxsBitmap;
   [ScrollView getFrameSize:&(nxrScrollView.size) forContentSize:&(nxrView.size) 
	      horizScroller:YES vertScroller:YES borderType:NX_NOBORDER];
   nxrScrollView.origin.x = nxrScrollView.origin.y = 0.0;	      
   scrollView = [ScrollView newFrame:&nxrScrollView];
   [[scrollView setVertScrollerRequired:YES] setHorizScrollerRequired:YES];
   [scrollView setDocView:self];
   
   /* the "origin" is a top left coordinate, convert it to lower left */
   nxrScrollView.origin.x = nxpTopLeft.x;	      
   [Window getFrameRect:&nxrWinHeight forContentRect:&nxrScrollView
                  style:NX_SIZEBARSTYLE];
   [NXApp getScreenSize:&nxsScreen];
   nxrScrollView.origin.y = nxsScreen.height - nxrWinHeight.size.height - nxpTopLeft.y;	      
   		  
   /* make the enclosing Window, and put the ScrollView (and View) in it */
   win = [Window newContent:&nxrScrollView style:NX_SIZEBARSTYLE backing:NX_BUFFERED defer:NO];
   [win setContentView:scrollView];
   [win setTitle:szTitle];
   [win display];
   [win makeKeyAndOrderFront:self];	
   [win setDelegate:self]; /* want this view to get messages about it's window */ 
   
   return( self );
   } /* newWindow 10/13/89 CFS */


/***************************************************************************/
/* windowWillResize - delegate message sent by window when user is resizes */
/* don't allow window to get bigger than is necessary to show whole image  */
/***************************************************************************/
- windowWillResize:sender toSize:(NXSize *)frameSize
   {
   NXRect	nxrScrollView;
   NXRect	nxrWinMax;
   
   /* find largest window necessary to hold bitmap */
   [ScrollView getFrameSize:&(nxrScrollView.size) forContentSize:&nxsBitmap 
	      horizScroller:YES vertScroller:YES borderType:NX_NOBORDER];
   [Window getFrameRect:&nxrWinMax forContentRect:&nxrScrollView 
	          style:NX_SIZEBARSTYLE];
		  
   /* prevent window fram from getting bigger than biggest necessary size */		  
   frameSize->width = MIN( nxrWinMax.size.width, frameSize->width );
   frameSize->height = MIN( nxrWinMax.size.height, frameSize->height );
   return( self );
   } /* windowWillResize 10/18/89 CFS */


/***************************************************************************/
/* free bitmap on closing - this is probably not necessary if the window   */
/* will free instance variable objects on closing                          */
/***************************************************************************/
- windowWillClose:sender
   {
   [closeNotify windowWillClose:[self window]];
   [bmpImage free];
   return( self );
   } /* windowWillClose 10/27/89 CFS */


/***************************************************************************/
/* drawSelf - simply composite the bitmap to the current focus		   */
/***************************************************************************/
- drawSelf:(NXRect *)r :(int) count
   {
   [bmpImage composite:NX_COPY fromRect:r toPoint:&(r->origin)];
   return( self );
   } /* drawSelf 8/16/89 CFS */


/***************************************************************************/
/* setMiniwindowIcon: - set the icon for miniturized state like window     */
/***************************************************************************/
- setMiniwindowIcon:(const char *)anIcon
   {
   [window setMiniwindowIcon:anIcon];
   return self;
   } /* setMiniwindowIcon 2/13/90 CFS */
   
   
/***************************************************************************/
/* saveBitmapToTiff - save the  bitmap in the given TIFF file              */
/***************************************************************************/
- (BOOL)saveBitmapToTiff:(const char *)fileName
   {
   #define	PERMISSION_MODE 0644 /* octal rw owner, r group, r others */
   NXStream	*stream;
   int 		fh;
   
   /* get a standard C file handle, and then a NeXT stream */
   fh = open( fileName, O_CREAT | O_TRUNC | O_WRONLY, PERMISSION_MODE );
   if (!(stream = NXOpenFile( fh, NX_WRITEONLY )))
      {
      [self errorAlert:"Couldn't open file for saving."];
      return( NO );
      }
      
   /* write the  bitmap out as a TIFF file */   
   [bmpImage writeTIFF:stream];
   
   /* close the stream and then the file handle */
   NXClose( stream );
   close( fh );
   return( YES );
   } /* saveBitmapToTiff 10/27/89 CFS */


/***************************************************************************/
/* errorAlert - put the message in an alert panel			   */
/***************************************************************************/
- errorAlert:(char *)szMessage
   {
   NXRunAlertPanel( "ViewBitmap Error", szMessage, "OK", NULL, NULL );
   return self;
   } /* errorAlert 10/30/89 CFS */


/***************************************************************************/
/* setCloseNotify: - optional object to notify when the window will close  */
/***************************************************************************/
- setCloseNotify:notify
   {
   closeNotify = notify;
   return( self );
   } /* setCloseNotify 1/31/90 CFS */

@end
