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 */ #endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.