/***(VdtWindow.m)**************************************************************
*H* Virtual Desk Top Window subclass implementation 	  	    	      *
******************************************************************************/

#import <stdio.h>

#import <appkit/Control.h>
#import <appkit/Panel.h>
#import <appkit/publicWraps.h>
#import <dpsclient/wraps.h>
#import <defaults.h>

#import "VdtWindow.h"
#import "VdtApplication.h"
#import "VdtView.h"
#import "nxkeycodes.h"

#ifdef DEBUG
void UTL_NxDumpEvent (NXEvent*, int, int, int);
#endif

#define MKpanHome 	    0
#define MKpanSouthWest 	    1
#define MKpanSouth 	    2
#define MKpanSouthEast	    3
#define MKpanWest   	    4
#define MKpanCenter   	    5
#define MKpanEast   	    6
#define MKpanNorthWest 	    7
#define MKpanNorth   	    8
#define MKpanNorthEast 	    9
#define MKpanTop   	    10
#define MKpanBottom   	    11
#define MKpanLeft   	    12
#define MKpanRight   	    13
#define MKpanTopLeft   	    14
#define MKpanTopRight  	    15
#define MKpanBottomLeft	    16
#define MKpanBottomRight    17


@implementation VdtWindow

- appDidBecomeActive:sender
{
#ifdef DEBUG
printf("VdtWindow- appDidBecomeActive:, windowNum=%d\n", windowNum);
#endif
return(self);
}


/******************************************************************************
* INSTANCE METHOD:- appDidInit:	    	    	    	    	    	      *
*   This method is  used  because  it  is the first time a valid windowNum is *
* available for the  WideScreen VDT window.   The windowNum of this window is *
* converted to  its  global  window  number  that  the DPS server uses.  This *
* window number is then used to avoid drawing itself in the VDT window.  This *
* method also sets the VDT window to default WindowLevel preference.	      *
******************************************************************************/
- appDidInit:sender

{/* BEGIN- appDidInit: */

/* Convert local window to its global server number */
NXConvertWinNumToGlobal(windowNum, (unsigned int*)&IVglobalWinNum);
[IVvdtView setVdtWindowNumber:IVglobalWinNum];

/* Set the VDT window to the Default WindowLevel */
[NXApp getDefaultWindowLevel:&IVselectedTag];
[self setVdtWindowLevel:self];

return(self);
}/* END- appDidInit: */



/******************************************************************************
* INSTANCE METHOD:- appWillTerminate:	    	    	    	    	      *
*   This method detects when the Quit command was selected and posts an alert *
* Panel giving the user the  opportunity  to 8confirm the quit request, or to *
* cancel the request.	    	    	    	    	    	    	      *
******************************************************************************/
- appWillTerminate:sender

{   /* Local Variables */
    int	choice;

/* BEGIN- appWillTerminate: */

/* Post the Quit confirmation Alert Panel and wait for a response */
choice = NXRunAlertPanel("Quit",
      	    	         "Are you sure wish to quit?",
            	    	 "Quit", "Cancel", NULL);
    	         
if ( choice == NX_ALERTDEFAULT )
    {/* The "Quit" button was clicked */
    /* Move the view port to its home origin before quiting */
    IVselectedTag = MKpanHome;
    [self panVdtViewPort:self];
    [IVvdtView retrieveDock:self];
    return(self);
    }

else if ( choice == NX_ALERTALTERNATE )
    {/* The "Cancel" button was clicked  */
#ifdef DEBUG
    printf("VdtWindow- appWillTerminate:, Cancel\n");
#endif
    return(nil);
    }

else if ( choice == NX_ALERTOTHER )
    {/*  */
#ifdef DEBUG
    printf("VdtWindow- appWillTerminate:, NX_ALERTOTHER\n");
#endif
    return(nil);
    }/*switch*/

return(nil);
}/* END- appWillTerminate: */



/******************************************************************************
* INSTANCE METHOD: - getGlobalWindowNum	    	    	    	    	      *
*   This method returns the  Display  PostScript servers global window number *
* assigned to the AppKits VdtWindow.	    	    	    	    	      *
******************************************************************************/
- (int) getGlobalWindowNum

{/* BEGIN getGlobalWindowNum */
return (IVglobalWinNum);
}/* END getGlobalWindowNum */



/******************************************************************************
* INSTANCE METHOD:- initContent:style:backing:buttonMask:defer:    	      *
*   This method  overrides  the  Window's  superclass  method.   It  uses the *
* WideScreen application defaults  to  override the IB defined width, height, *
* starting position of  the  VDT window.  Options for the window drag bar and *
* resize bar are also  set  from  the defaults.  This method also defines the *
* keyboard panning delta  by  the  view  port  panning functions.  All of the *
* instance variables are  initialized and this object is made the VdtWindow's *
* delegate. 	    	    	    	    	    	    	    	      *
******************************************************************************/
- initContent

    /* Arguments */
    :           (const NXRect*)contentRect
    style:      (int)aStyle
    backing:    (int)bufferingType
    buttonMask: (int)mask
    defer:      (BOOL)flag

{   /* Local Variables */
    int     defOriginX;
    int     defOriginY;
    int	    defPanDelta;
    int	    defResizeBar;
    int     defSizeH;
    int     defSizeW;
    int     defWinLocX;
    int     defWinLocY;
    NXSize  screenSize;
    NXRect  vdtWinRect;

/* BEGIN initContent:style:backing:buttonMask:defer: */
[NXApp setDelegate:self];

/* Get Virtual Desktop parameters, via defaults */
[NXApp getDefaultBorderGray:&IVborderGray];
[NXApp getDefaultImmobile:&IVisVdtImmobile];
[NXApp getDefaultOrigin:&defOriginX :&defOriginY];
[NXApp getDefaultPanDelta:&defPanDelta];
[NXApp getDefaultResizeBar:&defResizeBar];
[NXApp getDefaultScale:&IVvdtScale];
[NXApp getDefaultSize:&defSizeW :&defSizeH];
[NXApp getDefaultWinLoc:&defWinLocX :&defWinLocY];

/* Initialize VDT working parameters */
[NXApp getScreenSize:&screenSize];
NXSetRect(&IVvdtRect, 0.0, 0.0,
    	  screenSize.width*defSizeW, screenSize.height*defSizeH);
IVvdtOrigin.x = screenSize.width  * defOriginX;
IVvdtOrigin.y = screenSize.height * defOriginY;
IVpanDeltaX   = screenSize.width  * (defPanDelta / 100.0);
IVpanDeltaY   = screenSize.height * (defPanDelta / 100.0);

/* Define the size and position according to the default settings */
vdtWinRect.origin.x    = (float)defWinLocX;
vdtWinRect.origin.y    = (float)defWinLocY;
vdtWinRect.size.width  = IVvdtRect.size.width / IVvdtScale + 4.0;
vdtWinRect.size.height = IVvdtRect.size.height / IVvdtScale + 4.0;

/* Define the window attributes according to the defaults */
if ( defResizeBar )
 	 aStyle = NX_RESIZEBARSTYLE;
if ( IVisVdtImmobile )
    aStyle = NX_PLAINSTYLE;

/* Create the window that will contain the VdtView */
[super initContent:(const NXRect*) &vdtWinRect style:aStyle
       backing:bufferingType buttonMask:mask defer:flag];

IVglobalWinNum = -1;

[self setMiniwindowIcon:"MiniIcon.tiff"];
[self setDelegate:self];

return(self);
}/* END initContent:style:backing:buttonMask:defer: */



/******************************************************************************
* INTANCE METHOD:- keyDown:  	    	    	    	    	    	      *
*   This function captures key down events falling through to the main window *
* of the VDT application.   This  function  translates the key down events to *
* into simulated command key events for the Panning submenu.	    	      *
******************************************************************************/
- keyDown

    /* Arguments */
    :(NXEvent*) event

{/* BEGIN- keyDown: */
/***
 #ifdef DEBUG
 UTL_NxDumpEvent (event, 1, 1, 1);
 #endif
***/
if ( event->data.key.charCode == '0' )
    {/* The "Home" key was pressed */
    IVselectedTag = MKpanHome;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '1' )
    {/* The "SouthWest" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->BottomLeft */
    	IVselectedTag = MKpanBottomLeft;
    else
        /* No alternate key just do a Pan->SouthWest */
    	IVselectedTag = MKpanSouthWest;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '2' ||
    	  event->data.key.keyCode == NX_KEYCODE_DOWN )
    {/* The DOWN arrow or the "South" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->Bottom */
        IVselectedTag = MKpanBottom;
    else
        /* No alternate key just do a Pan->South */
        IVselectedTag = MKpanSouth;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '3' )
    {/* The "SouthEast" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->BottomRight */
        IVselectedTag = MKpanBottomRight;
    else
    	/* No alternate key just do a Pan->SouthEast */
        IVselectedTag = MKpanSouthEast;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '4' ||
    	  event->data.key.keyCode == NX_KEYCODE_LEFT )
    {/* The LEFT arrow or the "West" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->Left */
        IVselectedTag = MKpanLeft;
    else
        /* No alternate key just do a Pan->West */
        IVselectedTag = MKpanWest;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '5' )
    {/* The "Center" key was pressed */
    IVselectedTag = MKpanCenter;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '6' ||
    	  event->data.key.keyCode == NX_KEYCODE_RIGHT )
    {/* The RIGHT arrow or the "East" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->Right */
        IVselectedTag = MKpanRight;
    else
        /* No alternate key just do a Pan->East */
        IVselectedTag = MKpanEast;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '7' )
    {/* The "NorthWest" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
        /* The alternate key was held down perform Pan->TopLeft */
        IVselectedTag = MKpanTopLeft;
    else
        /* No alternate key just do a Pan->NorthWest */
        IVselectedTag = MKpanNorthWest;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '8' ||
     event->data.key.keyCode == NX_KEYCODE_UP )
    {/* The UP arrow or the "North" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
    	/* The alternate key was held down perform Pan->Top */
    	IVselectedTag = MKpanTop;
    else
    	/* No alternate key just do a Pan->North */ 
    	IVselectedTag = MKpanNorth;
    [self panVdtViewPort:self];
    }

else if ( event->data.key.charCode == '9' )
    {/* The "NorthEast" key was pressed */
    if ( (event->flags & NX_ALTERNATEMASK) )
    	/* The alternate key was held down perform Pan->TopRight */
        IVselectedTag = MKpanTopRight;
    else
        IVselectedTag = MKpanNorthEast;
    [self panVdtViewPort:self];
    }

return(self);
}/* END- keyDown: */



/******************************************************************************
* INSTANCE METHOD:- panVdtViewPort:                                           *
*   This method accepts  all  the  commands  from  the  Panner submenu.  This *
* method uses the  VdtView's  methods moveViewPortRel:: and moveViewPortAbs:: *
* to adjust the portion of  the  VDT  that  is  shown in the physical display *
* (i.e. the VdtViewPort).    	    	    	    	    	    	      *
******************************************************************************/
- panVdtViewPort:sender

{   /* Local Variables */
    NXPoint vdtCenter;
    NXSize  screenSize;
    float   maxPan = 100000.0;

/* BEGIN panVdtViewPort: */
#ifdef DEBUG
printf("VdtWindow- panVdtViewPort:, IVvdtView = %d\n", (int)IVvdtView);
#endif
switch ( [sender selectedTag] )
    {
    case MKpanHome: /* Home to view port origin */
    	[IVvdtView moveViewPortAbs:IVvdtOrigin.x :IVvdtOrigin.y];
    	break;

    case MKpanSouthWest:
    	[IVvdtView moveViewPortRel:-IVpanDeltaX :-IVpanDeltaY];
    	break;

    case MKpanSouth:
    	[IVvdtView moveViewPortRel:0.0 :-IVpanDeltaY];
    	break;

    case MKpanSouthEast:
    	[IVvdtView moveViewPortRel:IVpanDeltaX :-IVpanDeltaY];
    	break;

    case MKpanWest:
    	[IVvdtView moveViewPortRel:-IVpanDeltaX :0.0];
    	break;

    case MKpanCenter: /* Center View Port */
    	[NXApp getScreenSize:&screenSize];
    	vdtCenter.x = IVvdtRect.size.width/2.0  - screenSize.width/2.0;
    	vdtCenter.y = IVvdtRect.size.height/2.0 - screenSize.height/2.0;
    	[IVvdtView moveViewPortAbs:vdtCenter.x :vdtCenter.y];
    	break;

    case MKpanEast:
    	[IVvdtView moveViewPortRel:IVpanDeltaX :0.0];
    	break;

    case MKpanNorthWest:
    	[IVvdtView moveViewPortRel:-IVpanDeltaX :IVpanDeltaY];
    	break;

    case MKpanNorth:
    	[IVvdtView moveViewPortRel:0.0 :IVpanDeltaY];
    	break;

    case MKpanNorthEast:
    	[IVvdtView moveViewPortRel:IVpanDeltaX :IVpanDeltaY];
    	break;

    case MKpanTop:
    	[IVvdtView moveViewPortRel:0.0 :maxPan];
    	break;

    case MKpanBottom:
    	[IVvdtView moveViewPortRel:0.0 :-maxPan];
    	break;

    case MKpanLeft:
    	[IVvdtView moveViewPortRel:-maxPan :0.0];
    	break;

    case MKpanRight:
    	[IVvdtView moveViewPortRel:maxPan :0.0];
    	break;

    case MKpanTopLeft:
    	[IVvdtView moveViewPortRel:-maxPan :maxPan];
    	break;

    case MKpanTopRight:
    	[IVvdtView moveViewPortRel:maxPan :maxPan];
    	break;

    case MKpanBottomLeft:
    	[IVvdtView moveViewPortRel:-maxPan :-maxPan];
    	break;

    case MKpanBottomRight:
    	[IVvdtView moveViewPortRel:maxPan :-maxPan];
    	break;
    }/*switch*/

return(self);
}/* END panVdtViewPort: */



/******************************************************************************
* INSTANCE METHOD:- selectedTag	        	    	    	    	      *
*   This method serves to allow  the  VdtWindow to simulate a MenuCell sender *
* with a given tag value.   	    	    	    	    	    	      *
******************************************************************************/
- (int)selectedTag

{/* BEGIN- selectedTag */
return(IVselectedTag);
}/* END- selectedTag */



/******************************************************************************
* INSTANCE METHOD:- setVdtBorderGray:    	    	    	    	      *
*   This function changes the gray value used draw the Vdt Highlight border.  *
******************************************************************************/
- setVdtBorderGray

    /* Arguments */
    :(float)grayValue	    /*I* New Gray value to use as border gray */

{/* BEGIN- setVdtWindowLevel: */
IVborderGray = grayValue;

if ( IVisVdtImmobile )
    {/* Highlight the Vdt Window with the new grayValue border */
    [self setBackgroundGray:IVborderGray];
    [self display];
    }

return(self);
}/* END- setVdtWindowLevel: */



/******************************************************************************
* INSTANCE METHOD:- setVdtPanDelta:     	    	    	    	      *
*   This function changes the current  X and Y panning delta used in keyboard *
* panning according to the supplied PanDelta perctentage.   	    	      *
******************************************************************************/
- setVdtPanDelta

    /* Arguments */
    :(int)panDelta  	/*I* New Pan Delta Percentage */

{   /* Local Variables */
    NXSize  screenSize;

/* BEGIN- setVdtPanDelta */
[NXApp getScreenSize:&screenSize];

IVpanDeltaX   = screenSize.width  * (panDelta / 100.0);
IVpanDeltaY   = screenSize.height * (panDelta / 100.0);

return(self);
}/* END- setVdtPanDelta: */



/******************************************************************************
* INSTANCE METHOD:- setVdtWindowLevel:    	    	    	    	      *
*   This function changes the  windowing tier of the VDT desktop according to *
* selection made from the Level sub-menu.   	    	    	    	      *
******************************************************************************/
- setVdtWindowLevel:sender

{   /* Local Variables */
    int level = NX_FLOATINGLEVEL;

/* BEGIN- setVdtWindowLevel: */
switch ( [sender selectedTag] )
    {
    case 0:
    	level = NX_NORMALLEVEL;
    	break;

    case 1:
    	level = NX_FLOATINGLEVEL;
    	break;

    case 2:
    	level = NX_DOCKLEVEL;
    	break;

    case 3:
    	level = NX_SUBMENULEVEL;
    	break;

    case 4:
    	level = NX_MAINMENULEVEL;
    	break;
    }/*switch*/

PSsetwindowlevel(level, windowNum);

return(self);
}/* END- setVdtWindowLevel: */



/******************************************************************************
* INSTANCE METHOD:- windowDidBecomeKey:	    	    	    	    	      *
******************************************************************************/
- windowDidBecomeKey:sender

{/* BEGIN - windowDidBecomeKey: */
#ifdef DEBUG
printf("VdtWindow: -windowDidBecomeKey:\n");
#endif

return(self);
}/* END - windowDidBecomeKey: */



/******************************************************************************
* INSTANCE METHOD:- windowDidBecomeMain:    	    	    	    	      *
*   This method changes the VDT window's background gray to black, and issues *
* a display message to the window.  The effect is highlight the VDT view with *
* a black border since the VDT  view is 2 pixels smaller than the VDT windows *
* content view on each side.   Since  the  display message sent to the window *
* wil invoke the VDT  view's drawSelf:: method  this  function makes sure the *
* VDT view's window list is up to date before issueing the display message.   *
******************************************************************************/
- windowDidBecomeMain:sender

{/* BEGIN - windowDidBecomeMain: */

/* Update the window list before the VdtView gets display request */
[IVvdtView updateVdtView:self];

if ( IVisVdtImmobile )
    {/* Highlight the Vdt Window with the current BorderGray value */
    [self setBackgroundGray:IVborderGray];
    [self display];
    }

return(self);
}/* END - windowDidBecomeMain: */



/******************************************************************************
* INSTANCE METHOD:- windowDidResignMain:    	    	    	    	      *
*   This method changes the  VDT window's background gray back to light gray, *
* and issues a display message to the window.   The effect is unhighlight the *
* VDT view.  The display message also causes the VDT view to update.   	      *
******************************************************************************/
- windowDidResignMain:sender

{/* BEGIN - windowDidResignMain: */
if ( IVisVdtImmobile )
    {/* Unhilight the Vdt Window with a light gray border */
    [self setBackgroundGray:NX_LTGRAY];
    [self display];
    }

return(self);
}/* END - windowDidResignMain: */

@end
