This is VdtView.m in view mode; [Download] [Up]
/***(VdtView.m)****************************************************************
*H* Virtual Desk Top View subclass implementation *
******************************************************************************/
#import <stdlib.h>
#import <appkit/publicWraps.h>
#import <appkit/Control.h>
#import <appkit/Listener.h>
#import <appkit/NXImage.h>
#import <appkit/Speaker.h>
#import <dpsclient/dpsclient.h>
#import <dpsclient/dpswraps.h>
#import <dpsclient/wraps.h>
#import "VdtView.h"
#import "VdtApplication.h"
#import "VdtWindow.h"
#import "PswWindowOps.h"
/* Private Class Wide Definitions */
static CTwinInfo *FindWinfoByScaledPoint (NXPoint*, int, CTwinInfo*, int);
#ifdef PAN_GALACTIC_GARGLE_BLASTER
static CTwinInfo *FindWinfoByWindowNum (int, CTwinInfo*, int);
#endif
#define MKpswAbove 1
#define MKpswBelow -1
@implementation VdtView
/******************************************************************************
* INSTANCE METHOD:- initFrame: *
* This method overrides the View's superclass method. The - initFrame: *
* method gets called automatically when the object is instanciated. It used *
* to setup initial data structures and instance variables. *
******************************************************************************/
- initFrame
/* Arguments */
:(const NXRect*)frameRect /* The size and position of the view */
{ /* Local Variables */
int defOriginX;
int defOriginY;
int defSizeH;
int defSizeW;
int panGrid;
NXRect vdtFrame;
NXRect vdtRect;
/* BEGIN initFrame: */
/* Get Virtual Desktop parameters, via defaults */
[NXApp getDefaultDockHandling:&IVdockHandling];
[NXApp getDefaultOrigin:&defOriginX :&defOriginY];
[NXApp getDefaultPanJump:&IVvdtPanJump];
[NXApp getDefaultPanGrid:&panGrid];
[NXApp getDefaultScale:&IVvdtScale];
[NXApp getDefaultSize:&defSizeW :&defSizeH];
[NXApp getDefaultWindowMotion:&IVwindowMotion];
/* Initialize VDT working parameters */
[NXApp getScreenSize:&IVscreenSize];
NXSetRect(&vdtRect, 0.0, 0.0,
IVscreenSize.width*defSizeW, IVscreenSize.height*defSizeH);
/* Rework the View's frame rectangle to fit defaults settings */
vdtFrame.origin = frameRect->origin;
vdtFrame.size.width = vdtRect.size.width / IVvdtScale;
vdtFrame.size.height = vdtRect.size.height / IVvdtScale;
/* Perform superclass inits */
[super initFrame:(const NXRect*)&vdtFrame];
/* Initialize the off screen Stationary VDT image */
IVvdtStillImage = [[NXImage alloc] initSize:&vdtFrame.size];
[IVvdtStillImage setFlipped:NO];
IVvdtActualSize = vdtFrame.size;
IVvdtVirtualSize = vdtRect.size;
IVvdtOrigin.x = defOriginX * IVscreenSize.width / IVvdtScale;
IVvdtOrigin.y = defOriginY * IVscreenSize.height / IVvdtScale;
NXSetRect(&IVviewPort, IVvdtOrigin.x, IVvdtOrigin.y,
IVscreenSize.width/IVvdtScale, IVscreenSize.height/IVvdtScale);
/* Initialize instance variables */
IVwinInfoCount = 0;
IVwinInfoList = (CTwinInfo*)0;
IVvdtWinNum = -1;
IVvdtRootWinNum = -1;
IVstickyCount = 0;
IVstickySize = 0;
IVstickyTable = NULL;
[self setVdtPanGrid:panGrid];
/* Initialize the on screen window information list */
[self updateWindowList];
return(self);
}/* END initFrame: */
/******************************************************************************
* INSTANCE METHOD:- alignIcons: *
* This method finds all the Non-Docked icons within the current ViewPort, *
* and arranges them sequentially row upon row. The icons are bunched towards *
* given corner of the screen determined by the current Icon Gravity *
* preference. The right hand corners are set 67 pixels away from the edge of *
* the screen to leave room for the Dock. *
******************************************************************************/
- alignIcons:sender
{ /* Local Variables */
float curX; /* What column the next icon will be moved to */
int curY; /* What row the next icon will be moved to */
int deltaX; /* Direction to in Icon row */
int deltaY; /* Direction to in Icon column */
int gravity; /* 0:TopLeft 1:TopRight 2:BottomLeft 3:BottomRight */
int index; /* Loop Variable */
int iconsX; /* Number of icons that fit in the X dir */
int iconsY; /* Number of icons that fit in the Y dir */
float posX; /* New Y position of Icon to move */
float posY; /* New Y position of Icon to move */
float originX; /* Base position of Icon Row */
float originY; /* Base position of Icon Column */
NXRect viewPort; /* Actual size rectangle of VDT View Port */
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN-alignIcons: */
/* Make sure the Window Information List is accurate */
[self updateWindowList];
/* Get actual size of the rectangle for the current View Port */
viewPort.origin.x = 0.0;
viewPort.origin.y = 0.0;
viewPort.size = IVscreenSize;
/* Calculate the number of icons that can fit across the screen */
iconsX = (IVscreenSize.width - 64.0) / 64.0;
iconsY = IVscreenSize.height / 64.0;
/* Determine the positioning parameters according to the Icon Gravity */
[NXApp getDefaultIconGravity:&gravity];
if ( gravity == 0 )
{/* Set Top Left icon gravity parameters */
originX = 0.0;
originY = IVscreenSize.height - 64.0;
deltaX = 1;
deltaY = -1;
}
else if ( gravity == 1 )
{/* Set Top Right icon gravity parameters */
originX = IVscreenSize.width - 131.0;
originY = IVscreenSize.height - 64.0;
deltaX = -1;
deltaY = -1;
}
else if ( gravity == 3 )
{/* Set Bottom Right icon gravity parameters */
originX = IVscreenSize.width - 131.0;
originY = 0.0;
deltaX = -1;
deltaY = 1;
}
else
{/* Assume gravity of Bottom Left */
originX = 0.0;
originY = 0.0;
deltaX = 1;
deltaY = 1;
}
/* Loop through the window list, move any 64x64 window in the View Port */
curX = curY = 0;
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->level == NX_NORMALLEVEL &&
wiPtr->actualRect.size.width == 64.0 &&
wiPtr->actualRect.size.height == 64.0 &&
NXIntersectsRect(&viewPort, &wiPtr->actualRect) )
{/* This icon is within the current View Port Rect, so align it */
posX = originX + curX * deltaX * 64.0;
posY = originY + curY * deltaY * 64.0;
PswMoveWindow(wiPtr->number, posX, posY);
/* Calculate the position for the next Icon */
curX++;
if ( curX == iconsX )
{/* Start a new row of icons */
curX = 0;
curY++;
if ( curY == iconsY )
/* An awful lot of icons! Start piling them up */
curY = 0;
}
}/*if*/
}/*for*/
/* Update the VDT window representation */
[self updateVdtView:self];
return(self);
}/* END-alignIcons: */
/******************************************************************************
* INSTANCE METHOD:- dragVdtViewPort:: *
* This method is called from the mouse down method when the user presses *
* MB1 without any modifier keys and the cursor is inside the current VDT View *
* Port. This method waits until it actually detects the first drag event *
* before setting up an off screen image that will be composited into the view *
* as each drag event is processed. With each drag event the VdtView is *
* cleared to the background color and the View Port rectangle is drawn in its *
* new position. Then the still image containing all the window icons is *
* composited on top of the current VdtView. When a mouse up is detected the *
* change in the View Port's position is calculated and a moveViewPortAbs *
* message is sent to effect translation in the view port position. *
******************************************************************************/
- dragVdtViewPort
/* Arguments */
:(NXPoint*) startPos /* Point in the VdtView where the mouseDown occurred */
:(int) checkMask /* Event mask needed to get drag events */
{ /* Local Variables */
NXRect dragViewPort; /* VDT view port rectangle used in dragging */
NXRect dragBounds; /* Limiting rectangle to process drag events */
NXPoint deltaPoint; /* Delta X and Delta Y */
int firstDrag=1; /* Flag to indicate first drag event detected */
int keepDragging=1; /* Flag to be cleared when dragging over */
NXPoint newPos; /* Latest point of mouse drag */
NXEvent *nextEvent; /* Latest event from the event queue */
int panGridAdj; /* Integer for adjusting to PanGrid point */
/* BEGIN- dragVdtViewPort:: */
while ( keepDragging )
{
nextEvent = [NXApp getNextEvent:checkMask];
if ( nextEvent->type == NX_MOUSEUP )
keepDragging = 0;
else if ( nextEvent->type == NX_LMOUSEDRAGGED )
{
if ( firstDrag )
{/* First detected drag, do setup for subsequent drags */
/* Calculate the drag restraint rectangle */
deltaPoint.x = startPos->x - IVviewPort.origin.x;
deltaPoint.y = startPos->y - IVviewPort.origin.y;
NXSetRect(&dragBounds, bounds.origin.x, bounds.origin.y,
bounds.size.width - IVviewPort.size.width,
bounds.size.height - IVviewPort.size.height);
/* Create image of all stationary VDT objects durring ViewPort drag */
[IVvdtStillImage lockFocus];
[self renderVdt:0];
[IVvdtStillImage unlockFocus];
/* Set up view port rectangle to be dragged */
dragViewPort = IVviewPort;
deltaPoint.x = deltaPoint.y = 0.0;
[self lockFocus]; /* Lock focus on VdtView */
firstDrag = 0;
}/*if*/
/* Translate the current event to the VdtView coordinate space */
newPos = nextEvent->location;
[self convertPoint:&newPos fromView:nil];
/* Draw the VDT background and ViewPort */
PSsetgray(NX_DKGRAY);
NXRectFill(&bounds);
/* Calculate where to draw the VDT View Port from drag position */
deltaPoint.x = newPos.x - startPos->x;
deltaPoint.y = newPos.y - startPos->y;
dragViewPort.origin.x = IVviewPort.origin.x + deltaPoint.x;
dragViewPort.origin.y = IVviewPort.origin.y + deltaPoint.y;
/* Adjust new position to nearest PanGrid increment if needed */
if ( IVvdtPanGrid.x != 1.0 && IVvdtPanGrid.y != 1.0 )
{/* Adjust newPos to nearest grid point */
panGridAdj = dragViewPort.origin.x / IVvdtPanGrid.x + 0.5;
panGridAdj = panGridAdj * IVvdtPanGrid.x + 0.5;
dragViewPort.origin.x = panGridAdj;
panGridAdj = dragViewPort.origin.y / IVvdtPanGrid.y + 0.5;
panGridAdj = panGridAdj * IVvdtPanGrid.y + 0.5;
dragViewPort.origin.y = panGridAdj;
}
/* Limit the new origin to the dragging bounds */
if ( dragViewPort.origin.x < dragBounds.origin.x )
dragViewPort.origin.x = dragBounds.origin.x;
if ( dragViewPort.origin.x > dragBounds.size.width )
dragViewPort.origin.x = dragBounds.size.width;
if ( dragViewPort.origin.y < dragBounds.origin.y )
dragViewPort.origin.y = dragBounds.origin.y;
if ( dragViewPort.origin.y > dragBounds.size.height )
dragViewPort.origin.y = dragBounds.size.height;
/* Draw the View Port rectangle */
PSsetgray(NX_LTGRAY);
NXRectFill(&dragViewPort);
/* Then composite still image over background */
[IVvdtStillImage composite:NX_SOVER toPoint:&bounds.origin];
[window flushWindow]; // Needed else drawing is not shown
}/*if*/
}/*while*/
if ( !firstDrag )
{/* The view port was dragged unlockFocus and move the View Port */
[self unlockFocus];
[self moveViewPortAbs:dragViewPort.origin.x * IVvdtScale
:dragViewPort.origin.y * IVvdtScale];
}
return(self);
}/* END- dragVdtViewPort:: */
/******************************************************************************
* INSTANCE METHOD:- dragVdtWindow:: *
* This method is called from the mouse down method when the user presses *
* MB1 with the CONTROL key down. This method determines which window *
* represented in the VDT window that was clicked on. If the click located a *
* valid window this method process the events needed to drag the window *
* representation about the VDT window.
******************************************************************************/
- dragVdtWindow
/* Arguments */
:(NXPoint*) startPos /* Point in the VdtView where the mouseDown occurred */
:(int) checkMask /* Event mask needed to get drag events */
{ /* Local Variables */
NXPoint deltaPoint; /* Delta X and Delta Y */
NXRect dragBounds; /* Limiting rectangle to process drag events */
NXRect dragRect; /* VDT view port rectangle used in dragging */
int firstDrag=1; /* Flag to indicate first drag event detected */
int keepDragging=1; /* Flag to be cleared when dragging over */
NXPoint newPos; /* Latest point of mouse drag */
NXEvent *nextEvent; /* Latest event from the event queue */
CTwinInfo *wiPtr=0; /* Pointer to window info node of found window */
/* BEGIN- dragVdtWindow:: */
/* Locate the window by its scaled coordinates */
wiPtr = FindWinfoByScaledPoint(startPos, IVvdtWinNum,
IVwinInfoList, IVwinInfoCount);
/* Loop until a mouseUp event is received */
while ( keepDragging )
{
nextEvent = [NXApp getNextEvent:checkMask];
if ( nextEvent->type == NX_MOUSEUP )
keepDragging = 0;
else if ( nextEvent->type == NX_LMOUSEDRAGGED && wiPtr )
{
if ( firstDrag )
{/* First detected drag, do setup for subsequent drags */
/* Calculate the drag restraint rectangle */
deltaPoint.x = startPos->x - wiPtr->scaledRect.origin.x;
deltaPoint.y = startPos->y - wiPtr->scaledRect.origin.y;
NXSetRect(&dragBounds, bounds.origin.x, bounds.origin.y,
bounds.size.width - wiPtr->scaledRect.size.width,
bounds.size.height - wiPtr->scaledRect.size.height);
/* Create image of all stationary VDT objects durring window drag */
[IVvdtStillImage lockFocus];
[self renderVdt:wiPtr->number];
[IVvdtStillImage unlockFocus];
/* Set up view port rectangle to be dragged */
dragRect = wiPtr->scaledRect;
deltaPoint.x = deltaPoint.y = 0.0;
[self lockFocus];
firstDrag = 0;
}/*if*/
newPos = nextEvent->location;
[self convertPoint:&newPos fromView:nil];
/* Composite still image as background */
[IVvdtStillImage composite:NX_COPY toPoint:&bounds.origin];
/* Translate the drag window rectangle to the new drag position */
deltaPoint.x = newPos.x - startPos->x;
deltaPoint.y = newPos.y - startPos->y;
dragRect.origin.x = wiPtr->scaledRect.origin.x + deltaPoint.x;
if ( dragRect.origin.x < dragBounds.origin.x )
dragRect.origin.x = dragBounds.origin.x;
if ( dragRect.origin.x > dragBounds.size.width )
dragRect.origin.x = dragBounds.size.width;
dragRect.origin.y = wiPtr->scaledRect.origin.y + deltaPoint.y;
if ( dragRect.origin.y < dragBounds.origin.y )
dragRect.origin.y = dragBounds.origin.y;
if ( dragRect.origin.y > dragBounds.size.height )
dragRect.origin.y = dragBounds.size.height;
/* Next draw the scaled window in the VDT window */
PSsetgray(NX_WHITE);
NXRectFill(&dragRect);
PSsetgray(NX_BLACK);
PSrectstroke(dragRect.origin.x, dragRect.origin.y,
dragRect.size.width, dragRect.size.height);
if ( IVwindowMotion == 1 )
{/* Update the actual window position immediately */
wiPtr->actualRect.origin.x = (dragRect.origin.x - IVviewPort.origin.x) * IVvdtScale;
wiPtr->actualRect.origin.y = (dragRect.origin.y - IVviewPort.origin.y) * IVvdtScale;
PswMoveWindow(wiPtr->number,
wiPtr->actualRect.origin.x,
wiPtr->actualRect.origin.y);
}
[window flushWindow]; // Needed else drawing is not shown
}/*if*/
}/*while*/
if ( !firstDrag )
{/* The window was dragged unlockFocus and move the window */
[self unlockFocus];
wiPtr->scaledRect = dragRect;
wiPtr->actualRect.origin.x = (dragRect.origin.x - IVviewPort.origin.x) * IVvdtScale;
wiPtr->actualRect.origin.y = (dragRect.origin.y - IVviewPort.origin.y) * IVvdtScale;
PswMoveWindow(wiPtr->number,
wiPtr->actualRect.origin.x,
wiPtr->actualRect.origin.y);
[self updateVdtView:self];
}
return(self);
}/* END- dragVdtWindow:: */
/******************************************************************************
* INSTANCE METHOD: -drawSelf:: *
* The drawSelf:: method is invoked when Vdt is launched. It is also *
* invoked whenever a "display" message is received by this object. *
******************************************************************************/
- drawSelf
/* Arguments */
:(NXRect*)rects /* List of rectangular regions needing redrawing */
:(int)rectCount /* Number of rectangular regions in rects list */
{ /* Local Variables */
/* BEGIN drawSelf:: */
#ifdef DEBUG
printf("Executing 'drawSelf'\n");
#endif
[self renderVdt:-1];
return(self);
}/* END drawSelf:: */
/******************************************************************************
* INSTANCE METHOD:- mouseDown: *
* Overrides the Responder super-super class method. This method is invoked *
* each time a mouse button is pressed down inside VdtView.
******************************************************************************/
- mouseDown:(NXEvent*)theEvent
{ /* Local Variables */
int checkMask; /* Mask of events to be checked */
NXSize jumpDelta; /* Amount to Jump View Port in X and Y */
int mouseDown=1; /* Flag to clear when mousUp event received */
NXEvent *nextEvent; /* Next DPS event from the event queue */
int oldMask; /* Window event mask to restore when done */
NXPoint oldPos; /* Position of original mouse down */
CTwinInfo *wiPtr=NULL; /* Pointer to window info node of found window */
/* BEGIN- mouseDown: */
/* Make sure the window will deliver subsequent MouseUp&MouseDragged events */
oldMask = [window eventMask];
checkMask = oldMask | NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK;
[window setEventMask:checkMask];
/* Convert event location to VdtView coordinates */
oldPos = theEvent->location;
[self convertPoint:&oldPos fromView:nil];
/* Detetmine what action to perform according to modifier keys */
if ( (theEvent->flags & NX_ALTERNATEMASK) )
{/* Performing a stick/unstick operation */
#ifdef DEBUG
printf("VdtView- mouseDown NX_ALTERNATEMASK\n");
#endif
if ( NXPointInRect(&oldPos, &IVviewPort) )
{/* Only allowed to stick windows within ViewPort */
wiPtr = FindWinfoByScaledPoint(&oldPos, IVvdtWinNum,
IVwinInfoList, IVwinInfoCount);
if ( wiPtr )
{/* The click was within a window icon */
if ( wiPtr->sticky )
/* The window is marked sticky so unstick it */
[self stickyListDelete:wiPtr->number];
else
/* Window isn't currently sticky so mark it as sticky */
[self stickyListAdd:wiPtr->number];
}/*if*/
}/*if*/
}/*if*/
else if ( (theEvent->flags & NX_COMMANDMASK) )
{/* Performing a order window down operation */
wiPtr = FindWinfoByScaledPoint(&oldPos, IVvdtWinNum,
IVwinInfoList, IVwinInfoCount);
if ( wiPtr )
PswOrderWindow(MKpswBelow, 0, wiPtr->number);
}
else if ( (theEvent->flags & NX_CONTROLMASK) )
{/* Performing a move window operation */
[self dragVdtWindow:&oldPos :checkMask];
mouseDown = 0;
}
else if ( (theEvent->flags & NX_SHIFTMASK) )
{/* Performing a order up operation */
wiPtr = FindWinfoByScaledPoint(&oldPos, IVvdtWinNum,
IVwinInfoList, IVwinInfoCount);
if ( wiPtr )
PswOrderWindow(MKpswAbove, 0, wiPtr->number);
}
else if ( IVvdtPanJump )
{/* Then attempt to center View Port about mouse position */
jumpDelta.width = oldPos.x -
(IVviewPort.origin.x + IVviewPort.size.width/2.0);
jumpDelta.width *= IVvdtScale;
jumpDelta.height = oldPos.y -
(IVviewPort.origin.y + IVviewPort.size.height/2.0);
jumpDelta.height *= IVvdtScale;
[self moveViewPortRel:jumpDelta.width :jumpDelta.height];
/* Now begin normal View Port dragging from this point */
[self dragVdtViewPort:&oldPos :checkMask];
mouseDown = 0;
}
else if ( NXPointInRect(&oldPos, &IVviewPort) )
{/* Performing a move ViewPort operation */
[self dragVdtViewPort:&oldPos :checkMask];
mouseDown = 0;
}
/* Now take over event loop until a mouseUp event is detected */
while ( mouseDown )
{
nextEvent = [NXApp getNextEvent:checkMask];
if ( nextEvent->type == NX_MOUSEUP )
/* A mouseUp event was received, terminate loop */
mouseDown = 0;
}/*while*/
/* Restore the previous event mask */
[window setEventMask:oldMask];
/* Update the VDT window to reflect the current changes */
[self updateVdtView:self];
return(self);
}/* END mouseDown: */
/******************************************************************************
* INSTANCE METHOD:- moveViewPortAbs: *
* This method simulates moving the VDT View Port to a new absolute position.
******************************************************************************/
- moveViewPortAbs
/* Arguments */
:(float)newX
:(float)newY
{ /* Local Variables */
int index;
float oldX;
float oldY;
float deltaX;
float deltaY;
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN moveViewPortAbs */
[self updateWindowList];
/* Calculate the current ViewPort origin in VDT coordinates */
oldX = IVviewPort.origin.x * IVvdtScale;
oldY = IVviewPort.origin.y * IVvdtScale;
/* Make sure the desired origin is within the VDT limits */
if ( newX < 0.0 )
newX = 0.0;
if ( newX > IVvdtVirtualSize.width - IVscreenSize.width )
newX = IVvdtVirtualSize.width - IVscreenSize.width;
if ( newY < 0.0 )
newY = 0.0;
if ( newY > IVvdtVirtualSize.height - IVscreenSize.height )
newY = IVvdtVirtualSize.height - IVscreenSize.height;
/* Calculate the X,Y delta to be applied to each window to simulate **
** the ViewPort movement. */
deltaX = oldX - newX;
deltaY = oldY - newY;
/* Translate the VDT ViewPort origin to the VDT window scale */
IVviewPort.origin.x = newX / IVvdtScale;
IVviewPort.origin.y = newY / IVvdtScale;
/* Now run through the window list moving each window by deltaX,deltaY */
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = (IVwinInfoList+index);
if ( wiPtr->number != IVvdtWinNum &&
wiPtr->sticky == 0 && wiPtr->level >= 0 )
{/* This is not the VDT window so we move it */
wiPtr->actualRect.origin.x += deltaX;
wiPtr->actualRect.origin.y += deltaY;
PswMoveWindow(wiPtr->number,
wiPtr->actualRect.origin.x,
wiPtr->actualRect.origin.y);
}
}/*for*/
/* Redraw the VDT Window to reflect the window movement */
[self updateVdtView:self];
return(self);
}/* END moveViewPortAbs */
/******************************************************************************
* INSTANCE METHOD:- moveViewPortRel: *
* This method simulates moving the VDT View Port relative to its current *
* position.
******************************************************************************/
- moveViewPortRel
:(float)deltaX
:(float)deltaY
{ /* Local Variables */
int index;
float oldX;
float oldY;
float newX;
float newY;
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN moveViewPortRel */
[self updateWindowList];
oldX = IVviewPort.origin.x * IVvdtScale;
oldY = IVviewPort.origin.y * IVvdtScale;
newX = oldX + deltaX;
newY = oldY + deltaY;
if ( newX < 0.0 )
newX = 0.0;
if ( newX > IVvdtVirtualSize.width - IVscreenSize.width )
newX = IVvdtVirtualSize.width - IVscreenSize.width;
if ( newY < 0.0 )
newY = 0.0;
if ( newY > IVvdtVirtualSize.height - IVscreenSize.height )
newY = IVvdtVirtualSize.height - IVscreenSize.height;
deltaX = oldX - newX;
deltaY = oldY - newY;
IVviewPort.origin.x = newX / IVvdtScale;
IVviewPort.origin.y = newY / IVvdtScale;
/* Now run through the window list moving each window by deltaX,deltaY */
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->number != IVvdtWinNum &&
wiPtr->sticky == 0 && wiPtr->level >= 0 )
{
wiPtr->actualRect.origin.x += deltaX;
wiPtr->actualRect.origin.y += deltaY;
PswMoveWindow(wiPtr->number,
wiPtr->actualRect.origin.x,
wiPtr->actualRect.origin.y);
}
}/*for*/
/* Redraw the VDT Window to reflect the window movement */
[self updateVdtView:self];
return(self);
}/* END moveViewPortRel */
/******************************************************************************
* INSTANCE METHOD:- renderVdt: *
* This method is used to perform all the drawing of the VDT window.
******************************************************************************/
- renderVdt
/* Arguments */
:(int) outWin /* Window number of window not to be drawn */
{ /* Local Variables */
float borderColor; /* Color to draw window icon border */
float fillColor; /* Color to draw window icon interior */
int index; /* Loop Variable */
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN- renderVdt: */
if ( outWin == 0 )
{/* We are rendering the still image for a dragVdtViewPort */
/* Clear the still image for SOVER composite */
PScompositerect (bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height, NX_CLEAR);
}
else
{/* We are rendering for a still image for a dragVdtWindow, or we **
** are rendering for a normal drawSelf. */
/* First fill the entire Vdt View to Dark Grey */
PSsetgray(NX_DKGRAY);
NXRectFill(&bounds);
/* Next draw the the current view port as a light gray rectangle */
PSsetgray(NX_LTGRAY);
NXRectFill(&IVviewPort);
}
/* Now run through the window list bottom to top drawing a scaled rectangle */
/* of each window in the list. */
PSsetlinewidth(0.0);
for (index = IVwinInfoCount - 1; index > 0; index--)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->number != outWin &&
wiPtr->number != IVvdtWinNum && wiPtr->level >= 0 )
{/* Window NOT to be skipped, NOT VDT window, NOT background window */
if ( wiPtr->sticky )
{/* Set colors for sticky window */
borderColor = NX_WHITE;
fillColor = NX_BLACK;
}
else
{/* Set colors for normal window */
borderColor = NX_BLACK;
fillColor = NX_WHITE;
}
PSsetgray(fillColor);
NXRectFill(&wiPtr->scaledRect);
PSsetgray(borderColor);
PSrectstroke(wiPtr->scaledRect.origin.x, wiPtr->scaledRect.origin.y,
wiPtr->scaledRect.size.width, wiPtr->scaledRect.size.height);
}
}/*for*/
return(self);
}/* END- renderVdt: */
/******************************************************************************
* INSTANCE METHOD:- retrieveDock: *
* This method moves all the Dock Icons back within the current View Port. *
* The first step is to find the Dock Icon with the largest Y coordinate. *
* This is used to define the deltaY needed to reposition each of the Dock *
* Icons. The top Dock Icon is repositioned to the top right corner of the *
* screen and all the other Dock Icons are moved to the same relative Dock *
* Positions. *
******************************************************************************/
- retrieveDock:sender
{ /* Local Variables */
int index; /* Loop Variable */
float deltaY; /* Amount to change Dock Icons Y Origin */
float newX; /* New X to move Dock Icon to */
float newY; /* New Y to move Dock Icon to */
float topY; /* Y coordinate of the highest Dock Icon */
CTwinInfo *topWiPtr; /* Pointer to top Dock Icon IVwinInfoList node */
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN-retrieveDock: */
/* Make sure the Window Information List is accurate */
[self updateWindowList];
/* Locate the Dock Icon with the largest Y origin */
topY = -1000000.0;
topWiPtr = NULL;
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->level == NX_DOCKLEVEL && wiPtr->actualRect.origin.y > topY )
{/* This is a Dock Icon and it is higher than any so far */
topY = wiPtr->actualRect.origin.y;
topWiPtr = wiPtr;
}
}/*for*/
/* Calculate Y delta to move all dock icons by */
if ( topWiPtr )
{/* We have found a top Dock Icon so calculate Y delta to apply */
newY = IVscreenSize.height - 64.0;
deltaY = newY - topWiPtr->actualRect.origin.y;
}
else
deltaY = 0.0;
/* Now go through the Window List and move each Dock Icon */
newX = IVscreenSize.width - 67.0;
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->level == NX_DOCKLEVEL )
{/* This is a Dock Icon so calculate new position and move it */
newY = wiPtr->actualRect.origin.y + deltaY;
PswMoveWindow(wiPtr->number, newX, newY);
}
}/*for*/
[self updateVdtView:self];
return(self);
}/* END-retrieveDock: */
/******************************************************************************
* INSTANCE METHOD:- returnDock: *
* This method moves all the Dock Icons back to VDT Origin position. The *
* first step is to find the Dock Icon with the largest Y coordinate. This *
* is used to define the deltaY needed to reposition each of the Dock Icons. *
* The top Dock Icon is repositioned to the top right corner of the VDT Origin *
* relative to the current screen and all the other Dock Icons are moved to *
* the same relative Dock Positions. *
******************************************************************************/
- returnDock:sender
{ /* Local Variables */
int index; /* Loop Variable */
float deltaY; /* Amount to change Dock Icons Y Origin */
float newX; /* New X to move Dock Icon to */
float newY; /* New Y to move Dock Icon to */
float topY; /* Y coordinate of the highest Dock Icon */
CTwinInfo *topWiPtr; /* Pointer to top Dock Icon IVwinInfoList node */
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN-returnDock: */
if ( IVdockHandling == 0 )
/* The Dock handling is sticky disable this function */
/* NOTE: Should disable menu cell as well */
return(self);
/* Make sure the Window Information List is accurate */
[self updateWindowList];
/* Locate the Dock Icon with the largest Y origin */
topY = -1000000.0;
topWiPtr = NULL;
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->level == NX_DOCKLEVEL && wiPtr->actualRect.origin.y > topY )
{/* This is a Dock Icon and it is higher than any so far */
topY = wiPtr->actualRect.origin.y;
topWiPtr = wiPtr;
}
}/*for*/
/* Calculate Y delta to move all dock icons by */
if ( topWiPtr )
{/* We have found a top Dock Icon so calculate Y delta to apply */
newX = IVscreenSize.width - 67.0 +
IVvdtScale * (IVvdtOrigin.x - IVviewPort.origin.x);
newY = IVscreenSize.height - 64.0 +
IVvdtScale * (IVvdtOrigin.y - IVviewPort.origin.y);
deltaY = newY - topY;
}
else
return(self);
/* Now go through the Window List and move each Dock Icon */
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList+index;
if ( wiPtr->level == NX_DOCKLEVEL+1 )
{/* This is a Dock Icon so calculate new position and move it */
newY = wiPtr->actualRect.origin.y + deltaY;
PswMoveWindow(wiPtr->number, newX, newY);
}
}/*for*/
[self updateVdtView:self];
return(self);
}/* END-returnDock: */
/******************************************************************************
* INSTANCE METHOD:- setVdtPanGrid: *
* This method sets the mouse panning grid increment in both the X and Y *
* directions. The X and Y inrecrements are calculated based on the panGrid *
* value. The panGrid value expresses what percentage of the physical screen *
* width and height to use as the X increment and Y increment respectively. *
* If either value is less than 1.0 it is reset to 1.0 since the smallest grid *
* is limited to a single pixel in the VDT window. *
******************************************************************************/
- setVdtPanGrid
/* Arguments */
:(int)panGrid /*I* Percentage of screen to use as grid increment */
{ /* Local Variables */
NXSize screenSize;
/* BEGIN-setVdtPanGrid: */
[NXApp getScreenSize:&screenSize];
if ( panGrid > 0 )
{
IVvdtPanGrid.x = (screenSize.width * (panGrid / 100.0)) / IVvdtScale;
if ( IVvdtPanGrid.x < 1.0 )
IVvdtPanGrid.x = 1.0;
IVvdtPanGrid.y = (screenSize.height * (panGrid / 100.0)) / IVvdtScale;
if ( IVvdtPanGrid.y < 1.0 )
IVvdtPanGrid.y = 1.0;
}
else
IVvdtPanGrid.x = IVvdtPanGrid.y = 1.0;
return(self);
}/* END-setVdtPanGrid: */
/******************************************************************************
* INSTANCE METHOD:- setVdtPanJump: *
* This method changes sets the IVvdtPanJump flag which determines if Pan *
* Jumps should occur on an unmodified mouse click. *
******************************************************************************/
- setVdtPanJump
/* Arguments */
:(int)panJump /*I* Flag to indicate if Pan Jump is on or off */
{ /* Local Variables */
/* BEGIN setVdtPanJump: */
IVvdtPanJump = panJump;
return(self);
}/* END setVdtPanJump: */
/******************************************************************************
* INSTANCE METHOD:- setVdtWindowNumber: *
******************************************************************************/
- setVdtWindowNumber:(int)windowNum
{/* BEGIN setVdtWindowNumber: */
IVvdtWinNum = windowNum;
return(self);
}/* END setVdtWindowNumber: */
/******************************************************************************
* INSTANCE METHOD:- setViewDockHandling: *
* This sets the dock handling according to the Preference panel Dock *
* Handling selection. Setting the Dock handling to Sticky causes the Dock *
* Icons windows to be marked as sticky by the updateWindowList method. This *
* will cause all the dock icons to be treated as Sticky windows. *
******************************************************************************/
- setViewDockHandling
/* Arguments */
:(int)tagValue /* Tag value of the PrefPanel DockHandling selection */
{/* BEGIN-setViewDockHandling: */
IVdockHandling = tagValue;
if ( IVdockHandling == 0 )
[self retrieveDock:self];
else
[self updateVdtView:self];
return(self);
}/* END-setViewDockHandling: */
/******************************************************************************
* INSTANCE METHOD:- setViewWindowMotion: *
* This sets the window motion option according to the Preference panel *
* Window Motion selection. Setting the Window Motion to Immediate means that *
* the window associated with VDT window icon being dragged is moved in *
* tandem. If set to Deferred the actual window is not moved until the drag *
* of the VDT window icon is finished. *
******************************************************************************/
- setViewWindowMotion
/* Arguments */
:(int)tagValue /* Tag value of the PrefPanel WindowMotion selection */
{/* BEGIN-setViewWindowMotion: */
IVwindowMotion = tagValue;
return(self);
}/* END-setViewDockHandling: */
/******************************************************************************
* INSTANCE METHOD:- sizeTo:: *
* This method overrides the Views method to detect to what size the VDT *
* view being changed to. *
******************************************************************************/
- sizeTo
/* Arguments */
:(NXCoord)width
:(NXCoord)height
{/* BEGIN- sizeTo:: */
[super sizeTo:width :height];
/* Update the virtual size of the VDT */
IVvdtVirtualSize.width = bounds.size.width * IVvdtScale;
IVvdtVirtualSize.height = bounds.size.height * IVvdtScale;
/* Resize the dragging Still image to the same size as the VdtView */
[IVvdtStillImage setSize:&bounds.size];
return(self);
}/* END- sizeTo:: */
/******************************************************************************
* INSTANCE METHOD:- stickyListAdd: *
* This function adds a new window number to the sticky window table. If *
* not used the table is created. If insufficient space is available a larger *
* table is created. This method returns self for a succesfull add, and nil *
* otherwise. *
******************************************************************************/
- stickyListAdd:(int)windowNum
{ /* Local Variables */
int index; /* A loop variable */
int *newTable; /* Pointer to newly enlarged sticky table */
/* BEGIN-stickyListAdd: */
if ( IVstickyTable == NULL )
{/* The sticky table is unused, Initially set up the sticky table */
IVstickyTable = (int*)malloc(sizeof(int)*32);
if ( IVstickyTable )
{
IVstickySize = 32;
IVstickyCount = 0;
}
else
return(nil);
}
else if ( IVstickyCount >= IVstickySize )
{/* No room left in sticky table, try compressing then expanding */
/* Delete any long dead windows from the table */
[self stickyListPurge];
if ( IVstickyCount >= IVstickySize )
{/* Still no room, so increase the table size */
newTable = (int*)malloc(sizeof(int)*(IVstickySize+32));
if ( newTable )
{/* Copy old table and add new entry */
for (index = 0; index < IVstickySize; index++)
newTable[index] = IVstickyTable[index];
IVstickySize += 32;
free((char*)IVstickyTable);
IVstickyTable = newTable;
}
else
return(nil);
}/*if*/
}/*elseif*/
/* Add the new entry */
IVstickyTable[IVstickyCount++] = windowNum;
return(self);
}/* END-stickyListAdd: */
/******************************************************************************
* INSTANCE METHOD:- stickyListDelete: *
* This method removes a window number from the current sticky table. The *
* list elements that follow the deleted entry are moved up in the table so *
* that new entries can always be added to the end of the list. The method *
* returns self for a successful deletion, and nil otherwise. *
******************************************************************************/
- stickyListDelete
/* Arguments */
:(int)windowNum /*I* Window number to be removed from table */
{ /* Local Variables */
int findIndex; /* Sticky Table position of entry to delete */
int index; /* A loop variable */
/* BEGIN-stickyListDelete: */
if ( IVstickyTable != NULL )
{/* There is a table to search */
/* First search the table to find the supplied window number */
findIndex = -1;
index = 0;
while ( index < IVstickyCount && findIndex == -1)
{
if ( IVstickyTable[index] == windowNum )
findIndex = index;
else
index++;
}/*while*/
if ( findIndex != -1 )
{/* The entry was located, move all subsequent entries up one */
for ( index = findIndex; index < IVstickyCount; index++)
IVstickyTable[index] = IVstickyTable[index+1];
IVstickyCount--;
}
else
/* The entry was not found in the table, return failure status */
return(nil);
}/*if*/
else
/* The table is non-existant, return failure status */
return(nil);
return(self);
}/* END-stickyListDelete: */
/******************************************************************************
* INSTANCE METHOD:- stickyListPurge *
* This method removes from the list any window numbers that are no longer *
* DPS servers global window list. This method first gets a copy of the DPS *
* servers global window list. Then each entry in the sticky table is *
* searched for in the global window list. If the window is not found it is *
* marked for deletion. After the entire sitcky list is verified it is *
* scanned to remove any marked entries. *
******************************************************************************/
- stickyListPurge
{ /* Local Variables */
int found; /* Indicates if sticky entry in globalList */
int globalCount; /* Number of current DPS server windows */
int globalIndex; /* Loop Variable to scan globalList */
int *globalList; /* Top to bottom list of windows in server */
int stickyIndex; /* Loop Variable to scan sticky table */
/* BEGIN stickyListPurge */
/* Get the number of windows in the DPS servers global list */
PScountwindowlist(0, &globalCount);
/* Now retrieve the list of global window numbers */
globalList = (int*) malloc(globalCount*sizeof(int));
PSwindowlist(0, globalCount, globalList);
/* Validate each entry in sticky table is in the global window list */
for (stickyIndex = 0; stickyIndex < IVstickyCount; stickyIndex++)
{
/* Search for sticky table entry in global window list */
globalIndex = found = 0;
while ( !found && globalIndex < globalCount )
{
if ( globalList[globalIndex] == IVstickyTable[stickyIndex] )
found = 1;
}
if ( !found )
/* If the entry wasn't found mark it for deletion */
IVstickyTable[stickyIndex] = -1;
}/*for*/
/* Were done with the global list, so free it */
free((char*)globalList);
/* Now rescan the sticky table and remove any marked entries (== -1) */
globalIndex = 0; /* Reuse globalXxx vars as purgeXxx var */
for (stickyIndex = 0; stickyIndex < IVstickyCount; stickyIndex++)
{
if ( IVstickyTable[stickyIndex] != -1 )
/* This entry wasn't marked for deletion */
IVstickyTable[globalIndex++] = IVstickyTable[stickyIndex];
}
IVstickyCount = globalIndex;
return(self);
}/* END-stickyListPurge */
/******************************************************************************
* INSTANCE METHOD:- updateVdtView: *
* This method updates the window information list and then sends display *
* message to execute the drawSelf method to update the VdtView. *
******************************************************************************/
- updateVdtView:sender
{/* BEGIN updateVdtView: */
[self updateWindowList];
[self display];
return(self);
}/* END updateVdtView: */
/******************************************************************************
* INSTANCE METHOD:- updateWindowList *
******************************************************************************/
- updateWindowList
{ /* Local Variables */
int index; /* Loop Variable */
int screenCount; /* Number of current on screen windows */
int *screenList; /* Top to bottom list of windows on screen */
int stickyIndex; /* Loop variable for sticky table */
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
/* BEGIN updateWindowList */
/* Get the number of on screen windows. This doesn't mean that the window */
/* is visible within the physical screen viewport, but rather that is */
/* the root window. */
PScountscreenlist(0, &screenCount);
/* Now retrieve the list of global window numbers ordered from top to bottom */
screenList = (int*) malloc(screenCount*sizeof(int));
PSscreenlist(0, screenCount, screenList);
IVvdtRootWinNum = screenList[screenCount-1];
/* Ignore the bottom most window as it is not kosher */
screenCount--;
/* Allocate sufficient space to hold needed Info for each on screen window */
if ( IVwinInfoList == NULL )
{/* This is the first update, allocate an initial list */
IVwinInfoList = (CTwinInfo*) malloc(screenCount*sizeof(CTwinInfo));
}
else if ( screenCount > IVwinInfoCount )
{/* Need more space for the increased number of windows */
free((void*)IVwinInfoList);
IVwinInfoList = (CTwinInfo*) malloc(screenCount*sizeof(CTwinInfo));
}
IVwinInfoCount = screenCount;
/* Now get the position and size of each window in the list storing the data */
/* the IVwinInfoList. A pswrap function is used because the window numbers */
/* in the screenList are only valid in the global DPS context. */
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList + index;
wiPtr->number = screenList[index];
wiPtr->sticky = 0;
PswCurrentOwner(wiPtr->number, &wiPtr->context);
PswCurrentWindowLevel(wiPtr->number, &wiPtr->level);
PswCurrentWindowBounds(screenList[index],
&wiPtr->actualRect.origin.x,
&wiPtr->actualRect.origin.y,
&wiPtr->actualRect.size.width,
&wiPtr->actualRect.size.height);
wiPtr->scaledRect.origin.x = wiPtr->actualRect.origin.x / IVvdtScale +
IVviewPort.origin.x;
wiPtr->scaledRect.origin.y = wiPtr->actualRect.origin.y / IVvdtScale +
IVviewPort.origin.y;
wiPtr->scaledRect.size.width = wiPtr->actualRect.size.width / IVvdtScale;
wiPtr->scaledRect.size.height = wiPtr->actualRect.size.height / IVvdtScale;
/* Determine if the window is sticky */
if ( IVdockHandling == 0 && wiPtr->level == NX_DOCKLEVEL )
/* This is a dock icon and DockHandling is set to sticky */
wiPtr->sticky = 1;
else
{/* Check if the window is in the sticky table */
stickyIndex = 0;
while ( !wiPtr->sticky && stickyIndex < IVstickyCount )
{
if ( wiPtr->number == IVstickyTable[stickyIndex++] )
wiPtr->sticky = 1;
}
}
}/*for*/
free((void*)screenList);
return(self);
}/* END updateWindowList */
- Test_2:sender
{
int above;
int below;
PswWhatsAbove(&above);
PswWhatsBelow(&below);
printf("VdtView-Test_2 Above=%d Below=%d\n", above, below);
return(self);
}
- Test_1:sender
{ /* Local Variables */
int level;
int index;
float moveToX;
float moveToY;
int winToMove;
int status;
CTwinInfo *wiPtr; /* Pointer to node in IVwinInfoList */
static id speaker=nil;
/* BEGIN Test_1: */
[self updateWindowList];
IVvdtWinNum = [window getGlobalWindowNum];
printf("IVvdtWinNum local=%d global=%d\n",
[window windowNum], IVvdtWinNum);
printf("Screen List\n");
for (index = 0; index < IVwinInfoCount; index++)
{
wiPtr = IVwinInfoList + index;
PswCurrentWindowLevel(wiPtr->number, &level);
printf("screenList[%3d]=%4d (%2.1f,%2.1f) [%2.1f,%2.1f] L:%d\n",
index, wiPtr->number,
wiPtr->actualRect.origin.x, wiPtr->actualRect.origin.y,
wiPtr->actualRect.size.width, wiPtr->actualRect.size.height,
level);
}/*for*/
printf("Window to move: ");
scanf("%d", &winToMove);
if ( winToMove != -1 )
{
printf("Position: ");
scanf("%f %f", &moveToX, &moveToY);
printf("Moving Window %d to (%2.1f,%2.1f)\n", winToMove, moveToX, moveToY);
PswMoveWindow(winToMove, moveToX, moveToY);
if ( speaker == nil )
{
speaker = [NXApp appSpeaker];
[speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
}
status = [speaker performRemoteMethod:"updateViewers"];
printf("[speaker performRemoteMethod:'updateViewers'] = %d\n", status);
status = [speaker performRemoteMethod:"update"];
printf("[speaker performRemoteMethod:'update'] = %d\n", status);
}
return(self);
}/* END Test_1: */
@end /* VdtView */
/******************************************************************************
* FUNCTION: FindWinfoByScaledPoint *
* This function locates a Window Information list entry by returning a *
* pointer to the first entry that has a scaledRect that contains the supplied *
* point. *
******************************************************************************/
static CTwinInfo *FindWinfoByScaledPoint
(/* Arguments */
NXPoint *scaledPoint,
int ignoreWindow,
CTwinInfo *wiPtr,
int wiCount)
{ /* Local Variables */
int index;
/* BEGIN FindWinfoByScaledPoint */
for (index = 0; index < wiCount; index++)
{
if ( wiPtr->number != ignoreWindow && wiPtr->level >= 0 &&
NXPointInRect(scaledPoint, &wiPtr->scaledRect) )
return(wiPtr);
wiPtr++;
}
return((CTwinInfo*)0);
}/* END FindWinfoByScaledPoint */
#ifdef PAN_GALACTIC_GARGLE_BLASTER
/******************************************************************************
* FUNCTION: FindWinfoByWindowNum *
* This function locates a Window Information list entry by returning a *
* pointer to the first entry that has a number equal to the supplied window *
* number.
******************************************************************************/
static CTwinInfo *FindWinfoByWindowNum
(/* Arguments */
int windowNum,
CTwinInfo *wiPtr,
int wiCount)
{ /* Local Variables */
int index;
/* BEGIN FindWinfoByWindowNum */
for (index = 0; index < wiCount; index++)
{
if ( wiPtr->number == windowNum )
return(wiPtr);
wiPtr++;
}
fprintf(stderr,"ERROR: VdtView:FindWinfoByWindowNum failed for %d\n", windowNum);
return((CTwinInfo*)0);
}/* END FindWinfoByWindowNum */
#endifThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.