This is RuledScrollView.m in view mode; [Download] [Up]
// RuledScrollView.m // RuledScrollView is intended as a general purpose class to make it // easy to add all kinds of rulers to any view. This class is an // extension of the tiledScrollView class, from "ScrollDoodScroll" // (by Jayson Adams, NeXT Developer Support Team) // This class is intended to be widely useful without needing to // modify (or understand) its code, so it provides methods to setup // the mainView and its rulerViews, rather than hardcoding the setup. // Kevin Brain (ksbrain@zeus.UWaterloo.ca) #import <appkit/ClipView.h> #import <appkit/TextField.h> #import <appkit/Panel.h> #import "RuledScrollView.h" // Macro to print a rect (for debugging) #define PRINTRECT(string,rect) { \ printf(" %s x = %4.1f y = %4.1f width = %4.1f height = %4.1f\n",string, \ NX_X(&(rect)), NX_Y(&(rect)), NX_WIDTH(&(rect)), NX_HEIGHT(&(rect))); \ } @implementation RuledScrollView /* instance methods */ - initFrame:(NXRect *)theFrame { [super initFrame:theFrame]; rulersOn = YES; topRuler = NULL; bottomRuler = NULL; leftRuler = NULL; rightRuler = NULL; primaryRulers = TOPBOTTOM; return self; } - free { if (leftRuler) { [leftRuler free]; [leftRulerClipView free]; } if (rightRuler) { [rightRuler free]; [rightRulerClipView free]; } if (topRuler) { [topRuler free]; [topRulerClipView free]; } if (bottomRuler) { [bottomRuler free]; [bottomRulerClipView free]; } if (bottomLeftStub) { [bottomLeftStub free]; } if (topLeftStub) { [topLeftStub free]; } if (bottomRightStub) { [bottomRightStub free]; } if (topRightStub) { [topRightStub free]; } return [super free]; } - setLeftRuler:anObject { leftRuler = anObject; [self addRulerView:leftRuler toEdge:LEFTEDGE]; return self; } - setRightRuler:anObject { rightRuler = anObject; [self addRulerView:rightRuler toEdge:RIGHTEDGE]; return self; } - setTopRuler:anObject { topRuler = anObject; [self addRulerView:topRuler toEdge:TOPEDGE]; return self; } - setBottomRuler:anObject { bottomRuler = anObject; [self addRulerView:bottomRuler toEdge:BOTTOMEDGE]; return self; } - setBottomLeftStub:anObject { bottomLeftStub = anObject; [self addStubView:anObject toCorner: BOTTOMLEFTCORNER]; return self; } - setTopLeftStub:anObject { topLeftStub = anObject; [self addStubView:anObject toCorner: TOPLEFTCORNER]; return self; } - setBottomRightStub:anObject { bottomRightStub = anObject; [self addStubView:anObject toCorner: BOTTOMRIGHTCORNER]; return self; } - setTopRightStub:anObject { topRightStub = anObject; [self addStubView:anObject toCorner: TOPRIGHTCORNER]; return self; } - addRulerView:(Ruler *)theView toEdge:(int)edge { NXRect scaleViewRect; ClipView *scaleClipView; /* reset the origin of rulers created in nibs */ [theView getFrame:&scaleViewRect]; scaleViewRect.origin.x = 0.0; scaleViewRect.origin.y = 0.0; [theView setFrame:&scaleViewRect]; NXSetRect(&scaleViewRect,0,0,0,0); /* make a clipView to hold the scale view passed in * (we'll adjust its size & position in tile) */ scaleClipView = [[ClipView alloc] initFrame:&scaleViewRect]; [scaleClipView setDocView:theView]; [self addSubview:scaleClipView]; switch (edge) { case LEFTEDGE: // actually, I think we leak here if you add the same ruler twice // but I'm about to leave on holidays, so I can't be // bothered to change it now. Next version:-) if (leftRuler && (leftRuler != theView)) { // the view [leftRuler free]; [leftRulerClipView free]; } leftRuler = theView; leftRulerClipView = scaleClipView; if([leftRuler respondsTo:@selector(setOrientation:)]) [leftRuler setOrientation:VERTICAL]; // default is horizontal break; case RIGHTEDGE: if (rightRuler && (rightRuler != theView)) { [rightRuler free]; [rightRulerClipView free]; } rightRuler = theView; rightRulerClipView = scaleClipView; if([rightRuler respondsTo:@selector(setOrientation:)]) [rightRuler setOrientation:VERTICAL]; // default is horizontal break; case TOPEDGE: if (topRuler && (topRuler != theView)) { [topRuler free]; [topRulerClipView free]; } topRuler = theView; topRulerClipView = scaleClipView; break; case BOTTOMEDGE: if (bottomRuler && (bottomRuler != theView)) { [bottomRuler free]; [bottomRulerClipView free]; } bottomRuler = theView; bottomRulerClipView = scaleClipView; break; } rulerVisible[edge] = YES; // turn this ruler on by default return self; } - addStubView:(View *)theView toCorner:(int)corner { switch (corner) { case BOTTOMLEFTCORNER: if (bottomLeftStub && (bottomLeftStub != theView)) [bottomLeftStub free]; bottomLeftStub = theView; break; case TOPLEFTCORNER: if (topLeftStub && (topLeftStub != theView)) [topLeftStub free]; topLeftStub = theView; break; case BOTTOMRIGHTCORNER: if (bottomRightStub && (bottomRightStub != theView)) [bottomRightStub free]; bottomRightStub = theView; break; case TOPRIGHTCORNER: if (topRightStub && (topRightStub != theView)) [topRightStub free]; topRightStub = theView; break; } [self addSubview:theView]; return self; } - sliceEdge:(int)theEdge forRuler:theRuler inClipView:theClipView // private method that cuts a slice from the contentView to make room for a ruler { NXRect contentViewRect, scaleRect, scaleClipRect; NXRect cvBoundsRect; // get bounds of contentView so we can reset it after setting frame [contentView getBounds:&cvBoundsRect]; [contentView getFrame:&contentViewRect]; [theRuler getFrame:&scaleRect]; if ((theEdge == LEFTEDGE) || (theEdge == RIGHTEDGE)) NXDivideRect(&contentViewRect, &scaleClipRect, NX_WIDTH(&scaleRect), theEdge); else NXDivideRect(&contentViewRect, &scaleClipRect, NX_HEIGHT(&scaleRect), theEdge); [theClipView setFrame:&scaleClipRect]; // invokes reflectScroll: // setting contentView's frame changes contentView bounds then invokes reflectScroll: [contentView setFrame:&contentViewRect]; // reset bounds of contentView mangled by setting frame [self scrollClip:contentView to:(NXPoint *)&cvBoundsRect.origin]; return self; } - tile /* * tile gets called whenever the scrollView changes size. Its job is to resize * all of the scrollView's "tiled" views (scrollers, contentView and any other * views we might want to place in the scrollView's bounds). */ { NXRect viewRect, scrollerRect, tempRect, cvBounds, newCVBounds; NXRect stubRect, rulerClipRect, otherRulerRect, docViewRect; float tempFloat=0.0,distanceFromEdge; [contentView getBounds:&cvBounds]; [[self docView] getBounds:&docViewRect]; /* resize and arrange the scrollers and contentView as usual */ [super tile]; // invokes reflectScroll: // If the scroller knob is closer to the edge than the width or height // of the ruler views, the tile method causes the contentView bounds // to be incorrectly changed. After many frustrating hours of work, // I came up with the following code to correct for this... [contentView getBounds:&newCVBounds]; NXSetRect(&otherRulerRect,0,0,0,0); [[self leftRuler] getFrame:&otherRulerRect]; if ([self isRulerVisible:LEFTEDGE]) tempFloat = otherRulerRect.size.width; NXSetRect(&otherRulerRect,0,0,0,0); [[self rightRuler] getFrame:&otherRulerRect]; if ([self isRulerVisible:RIGHTEDGE]) tempFloat += otherRulerRect.size.width; distanceFromEdge = docViewRect.size.width - (cvBounds.origin.x+cvBounds.size.width); // if entire width of docView was showing, don't adjust if (cvBounds.size.width > docViewRect.size.width) distanceFromEdge = tempFloat; if ((distanceFromEdge < tempFloat) && (newCVBounds.size.width < docViewRect.size.width)) newCVBounds.origin.x += (tempFloat-distanceFromEdge); NXSetRect(&otherRulerRect,0,0,0,0); [[self topRuler] getFrame:&otherRulerRect]; if ([self isRulerVisible:TOPEDGE]) tempFloat = otherRulerRect.size.height; NXSetRect(&otherRulerRect,0,0,0,0); [[self bottomRuler] getFrame:&otherRulerRect]; if ([self isRulerVisible:BOTTOMEDGE]) tempFloat += otherRulerRect.size.height; distanceFromEdge = docViewRect.size.height - (cvBounds.origin.y+cvBounds.size.height); // if entire height of docView was showing, don't adjust if (cvBounds.size.height > docViewRect.size.height) distanceFromEdge = tempFloat; if ((distanceFromEdge < tempFloat) && (newCVBounds.size.height < docViewRect.size.height)) newCVBounds.origin.y += (tempFloat-distanceFromEdge); // correct contentView Bounds [self scrollClip:contentView to:(NXPoint *)&newCVBounds.origin]; /* cut a slice from the contentView to make room for each scaleView */ if (primaryRulers == TOPBOTTOM) { if(topRuler && rulerVisible[TOPEDGE]) { if ([self isFlipped]) [self sliceEdge:(int)BOTTOMEDGE forRuler:topRuler inClipView:topRulerClipView]; else [self sliceEdge:(int)TOPEDGE forRuler:topRuler inClipView:topRulerClipView]; } if(bottomRuler && rulerVisible[BOTTOMEDGE]) { if ([self isFlipped]) [self sliceEdge:(int)TOPEDGE forRuler:bottomRuler inClipView:bottomRulerClipView]; else [self sliceEdge:(int)BOTTOMEDGE forRuler:bottomRuler inClipView:bottomRulerClipView]; } if(leftRuler && rulerVisible[LEFTEDGE]) [self sliceEdge:(int)LEFTEDGE forRuler:leftRuler inClipView:leftRulerClipView]; if(rightRuler && rulerVisible[RIGHTEDGE]) [self sliceEdge:(int)RIGHTEDGE forRuler:rightRuler inClipView:rightRulerClipView]; // Add stub views (now that edge views are present) if(topRuler && rulerVisible[TOPEDGE]) { if (topLeftStub) { [leftRulerClipView getFrame:&otherRulerRect]; [topRulerClipView getFrame:&rulerClipRect]; NXDivideRect(&rulerClipRect, &stubRect, otherRulerRect.size.width, LEFTEDGE); [topRulerClipView setFrame:&rulerClipRect]; [topLeftStub setFrame:&stubRect]; } if (topRightStub) { [rightRulerClipView getFrame:&otherRulerRect]; [topRulerClipView getFrame:&rulerClipRect]; NXDivideRect(&rulerClipRect, &stubRect, otherRulerRect.size.width, RIGHTEDGE); [topRulerClipView setFrame:&rulerClipRect]; [topRightStub setFrame:&stubRect]; } } if(bottomRuler && rulerVisible[BOTTOMEDGE]) { if (bottomLeftStub) { [leftRulerClipView getFrame:&otherRulerRect]; [bottomRulerClipView getFrame:&rulerClipRect]; NXDivideRect(&rulerClipRect, &stubRect, otherRulerRect.size.width, LEFTEDGE); [bottomRulerClipView setFrame:&rulerClipRect]; [bottomLeftStub setFrame:&stubRect]; } if (bottomRightStub) { [rightRulerClipView getFrame:&otherRulerRect]; [bottomRulerClipView getFrame:&rulerClipRect]; NXDivideRect(&rulerClipRect, &stubRect, otherRulerRect.size.width, RIGHTEDGE); [bottomRulerClipView setFrame:&rulerClipRect]; [bottomRightStub setFrame:&stubRect]; } } } else { if(leftRuler && rulerVisible[LEFTEDGE]) [self sliceEdge:(int)LEFTEDGE forRuler:leftRuler inClipView:leftRulerClipView]; if(rightRuler && rulerVisible[RIGHTEDGE]) [self sliceEdge:(int)RIGHTEDGE forRuler:rightRuler inClipView:rightRulerClipView]; if(topRuler && rulerVisible[TOPEDGE]) { if ([self isFlipped]) [self sliceEdge:(int)BOTTOMEDGE forRuler:topRuler inClipView:topRulerClipView]; else [self sliceEdge:(int)TOPEDGE forRuler:topRuler inClipView:topRulerClipView]; } if(bottomRuler && rulerVisible[BOTTOMEDGE]) { if ([self isFlipped]) [self sliceEdge:(int)TOPEDGE forRuler:bottomRuler inClipView:bottomRulerClipView]; else [self sliceEdge:(int)BOTTOMEDGE forRuler:bottomRuler inClipView:bottomRulerClipView]; } /****************************************************************************/ /* Code to tile StubViews when (primaryRulers != TOPBOTTOM) still missing */ /****************************************************************************/ } // The following imbeds a view (normally a button) in the horizontal scroller // if the hScrollerRightEmbeddedView instance variable is connected to some view (in IB) // A textfield with Courier-Medium size 10 font will fit into the horizontal scroller. if (hScrollerRightEmbeddedView) { if ([hScrollerRightEmbeddedView superview] != self) { [self addSubview:hScrollerRightEmbeddedView]; } [hScrollerRightEmbeddedView getFrame:&tempRect]; // now make the hScroller smaller and stick the popupList next to it [hScroller getFrame:&scrollerRect]; // width stored during init NXDivideRect(&scrollerRect, &viewRect, tempRect.size.width, RIGHTEDGE); // Need to force width back to original button width since the above function // will not set viewRect.size.width to tempRect.size.width when the // tile method is evoked before the correct size of the mainView is set viewRect.size.width = tempRect.size.width; [hScroller setFrame:&scrollerRect]; NXInsetRect(&viewRect, 0, 1.0); [hScrollerRightEmbeddedView setFrame:&viewRect]; } // Do the same as above for a possible second view in the horizontal scroller if (hScrollerLeftEmbeddedView) { if ([hScrollerLeftEmbeddedView superview] != self) { [self addSubview:hScrollerLeftEmbeddedView]; } [hScrollerLeftEmbeddedView getFrame:&tempRect]; [hScroller getFrame:&scrollerRect]; NXDivideRect(&scrollerRect, &viewRect, tempRect.size.width, RIGHTEDGE); viewRect.size.width = tempRect.size.width; [hScroller setFrame:&scrollerRect]; NXInsetRect(&viewRect, 0, 1.0); [hScrollerLeftEmbeddedView setFrame:&viewRect]; } // Do the same as above for a view in the vertical scroller if (vScrollerTopEmbeddedView) { if ([vScrollerTopEmbeddedView superview] != self) { [self addSubview:vScrollerTopEmbeddedView]; } [vScrollerTopEmbeddedView getFrame:&tempRect]; [vScroller getFrame:&scrollerRect]; if ([self isFlipped]) NXDivideRect(&scrollerRect, &viewRect, tempRect.size.height, BOTTOMEDGE); else NXDivideRect(&scrollerRect, &viewRect, tempRect.size.height, TOPEDGE); viewRect.size.height = tempRect.size.height; [vScroller setFrame:&scrollerRect]; NXInsetRect(&viewRect, 1.0, 0); [vScrollerTopEmbeddedView setFrame:&viewRect]; } // Do the same as above for a possible second view in the vertical scroller if (vScrollerBottomEmbeddedView) { if ([vScrollerBottomEmbeddedView superview] != self) { [self addSubview:vScrollerBottomEmbeddedView]; } [vScrollerBottomEmbeddedView getFrame:&tempRect]; [vScroller getFrame:&scrollerRect]; if ([self isFlipped]) NXDivideRect(&scrollerRect, &viewRect, tempRect.size.height, BOTTOMEDGE); else NXDivideRect(&scrollerRect, &viewRect, tempRect.size.height, TOPEDGE); viewRect.size.height = tempRect.size.height; [vScroller setFrame:&scrollerRect]; NXInsetRect(&viewRect, 1.0, 0); [vScrollerBottomEmbeddedView setFrame:&viewRect]; } // save the size of the docView for setSizeIfNeeded [[self docView] getFrame:&oldRect]; return self; } - reflectScroll:cView // does not affect contentView bounds... /* * We only reflect scroll in the contentView, not the scale views. */ { return [super reflectScroll:contentView]; } - scrollClip:aClipView to:(NXPoint *)aPoint { NXPoint colOrigin,newPoint; NXRect colBounds; newPoint = *aPoint; // if it's not the contentView, adjust the point being scrolled to so that // it doesn't scroll the contentView except in the direction of the ruler [contentView getBounds:&colBounds]; if (aClipView != contentView) if(([aClipView docView] == leftRuler) || ([aClipView docView] == rightRuler)) newPoint.x = colBounds.origin.x; else newPoint.y = colBounds.origin.y; /* turn off drawing (to the screen) */ [window disableFlushWindow]; /* scroll the contentView to the new origin */ [contentView rawScroll:&newPoint]; /* compute new origin for the leftRulerView (don't let it scroll horizontally) */ [leftRulerClipView getBounds:&colBounds]; colOrigin.x = colBounds.origin.x; colOrigin.y = newPoint.y; [leftRulerClipView rawScroll:&colOrigin]; // scroll the scale view to that point /* compute new origin for the rightRulerView (don't let it scroll horizontally) */ [rightRulerClipView getBounds:&colBounds]; colOrigin.x = colBounds.origin.x; colOrigin.y = newPoint.y; [rightRulerClipView rawScroll:&colOrigin]; // scroll the scale view to that point /* compute new origin for the topRulerView (don't let it scroll vertically) */ [topRulerClipView getBounds:&colBounds]; colOrigin.x = newPoint.x ; colOrigin.y = colBounds.origin.y; [topRulerClipView rawScroll:&colOrigin]; // scroll the scale view to that point /* compute new origin for the bottomRulerView (don't let it scroll vertically) */ [bottomRulerClipView getBounds:&colBounds]; colOrigin.x = newPoint.x ; colOrigin.y = colBounds.origin.y; [bottomRulerClipView rawScroll:&colOrigin]; // scroll the scale view to that point /* send results to screen */ [[window reenableFlushWindow] flushWindow]; return self; } - setSizeIfNeeded { NXRect theFrame; [[self docView] getFrame:&theFrame]; if ((theFrame.size.width != oldRect.size.width) || (theFrame.size.height != oldRect.size.height)) [self setSize]; return self; } - setSize // This method must be invoked whenever the size // of the mainView is changed. { NXRect theFrame; [window disableDisplay]; if (topRuler) [topRuler setSize]; if (bottomRuler) [bottomRuler setSize]; if (leftRuler) [leftRuler setSize]; if (rightRuler) [rightRuler setSize]; [self resizeSubviews:(const NXSize *)&theFrame.size]; [[window reenableDisplay] displayIfNeeded]; return self; } - showRuler:(int)whichRuler; { rulerVisible[whichRuler] = YES; switch (whichRuler) { case TOPEDGE: if (topRulerClipView) { [self addSubview:topRulerClipView]; if (leftRulerClipView && rulerVisible[LEFTEDGE]&& topLeftStub) [self addSubview:topLeftStub]; if (rightRulerClipView && rulerVisible[RIGHTEDGE]&& topRightStub) [self addSubview:topRightStub]; } break; case BOTTOMEDGE: if (bottomRulerClipView) { [self addSubview:bottomRulerClipView]; if (leftRulerClipView && rulerVisible[LEFTEDGE]&& bottomLeftStub) [self addSubview:bottomLeftStub]; if (rightRulerClipView && rulerVisible[RIGHTEDGE]&& bottomRightStub) [self addSubview:bottomRightStub]; } break; case LEFTEDGE: if (leftRulerClipView) { [self addSubview:leftRulerClipView]; if (topRulerClipView && rulerVisible[TOPEDGE]&& topLeftStub) [self addSubview:topLeftStub]; if (bottomRulerClipView && rulerVisible[BOTTOMEDGE]&& bottomLeftStub) [self addSubview:bottomLeftStub]; } break; case RIGHTEDGE: if (rightRulerClipView) { [self addSubview:leftRulerClipView]; if (topRulerClipView && rulerVisible[TOPEDGE]&& topRightStub) [self addSubview:topRightStub]; if (bottomRulerClipView && rulerVisible[BOTTOMEDGE]&& bottomRightStub) [self addSubview:bottomRightStub]; } break; } return self; } - hideRuler:(int)whichRuler; // this should be followed promptly with a setSize { rulerVisible[whichRuler] = NO; switch (whichRuler) { case TOPEDGE: if (topRulerClipView) [topRulerClipView removeFromSuperview]; if (topLeftStub) [topLeftStub removeFromSuperview]; if (topRightStub) [topRightStub removeFromSuperview]; break; case BOTTOMEDGE: if (bottomRulerClipView) [bottomRulerClipView removeFromSuperview]; if (bottomLeftStub) [bottomLeftStub removeFromSuperview]; if (bottomRightStub) [bottomRightStub removeFromSuperview]; break; case LEFTEDGE: if (leftRulerClipView) [leftRulerClipView removeFromSuperview]; if (topLeftStub) [topLeftStub removeFromSuperview]; if (bottomLeftStub) [bottomLeftStub removeFromSuperview]; break; case RIGHTEDGE: if (rightRulerClipView) [rightRulerClipView removeFromSuperview]; if (bottomRightStub) [bottomRightStub removeFromSuperview]; if (topRightStub) [topRightStub removeFromSuperview]; break; } return self; } - (BOOL)isRulerVisible:(int)whichRuler { return rulerVisible[whichRuler]; } - topRuler { return topRuler; } - bottomRuler { return bottomRuler; } - leftRuler { return leftRuler; } - rightRuler { return rightRuler; } - setPrimaryRulers:(int)orientation { primaryRulers = orientation; return self; } - bottomLeftStub { return bottomLeftStub; } - topLeftStub { return topLeftStub; } - bottomRightStub { return bottomRightStub; } - topRightStub { return topRightStub; } - (int)primaryRulers { return primaryRulers; } - getMinSize:(NXSize *)theSize { NXRect contentViewRect,ruledScrollViewRect; [contentView getFrame:&contentViewRect]; [self getFrame:&ruledScrollViewRect]; theSize->width = ruledScrollViewRect.size.width - contentViewRect.size.width+1; theSize->height = ruledScrollViewRect.size.height - contentViewRect.size.height+1; return self; } /* methods for printing the visible view */ /*---------------------------------------*/ - createPrintView // Creates a view for printing the visible part of the trace // We do this by adding the rulerViews' ClipViews as subviews to a View object // (printView) which is allocated once and added as a subview of // an offscreen window. When we are done with them, we return the // ClipViews to their former position as subviews of the RuledScrollView object // (self). The mainView itself is also taken (rather than its ClipView) // and added to another ClipView object (mainPrintClipView), since it proved // troublesome to return the mainView (docView) itself when finished with it. { float leftOffset; NXRect tempRect, clipFrame; NXRect oldMainClipBounds, oldMainFrame; if (!printWindow) { // create window & setup mainPrintClipView first time through // note that size is fixed at 1120 X 832 NXSetRect(&tempRect, (NXCoord) 0, (NXCoord) 0, (NXCoord) 1120, (NXCoord) 832); /* create a window for printView */ printWindow = [[Window alloc] initContent:(const NXRect *)&tempRect style:(int)NX_PLAINSTYLE // no title bar and frame backing:(int)NX_BUFFERED buttonMask:(int)0 // no controls in title bar and frame defer:(BOOL)NO]; NXSetRect(&tempRect, (NXCoord) 0, (NXCoord) 0, (NXCoord) 0, (NXCoord) 0); printView = [[View alloc] initFrame:&tempRect]; if ([self isFlipped]) [printView setFlipped:YES]; mainPrintClipView = [[ClipView alloc] initFrame:&tempRect]; [[printWindow contentView] addSubview:printView]; } /* set pointer to the main View */ mainView = [self docView]; /* get translation information (which part of main view is visible) */ /* we will scroll the main View in its new clipView (a subview of */ /* PrintView) by sending a scrollPoint: message to it with the point */ /* (main View's clipView's bounds.origin) - (main View's Frame.origin) */ [[mainView superview] getBounds:&oldMainClipBounds]; [mainView getFrame:&oldMainFrame]; mainVisiblePoint.x = oldMainClipBounds.origin.x - oldMainFrame.origin.x; mainVisiblePoint.y = oldMainClipBounds.origin.y - oldMainFrame.origin.y; // put mainPrintClipView in the same place as it is in ruledScrollView [[mainView superview] getFrame:&oldMainClipRect]; /* get current locations of clipviews */ // NXSetRect(&oldBottomRect,0,0,0,0); // NXSetRect(&oldTopRect,0,0,0,0); // NXSetRect(&oldLeftRect,0,0,0,0); // NXSetRect(&oldRightRect,0,0,0,0); [bottomRulerClipView getFrame:&oldBottomRect]; [topRulerClipView getFrame:&oldTopRect]; [leftRulerClipView getFrame:&oldLeftRect]; [rightRulerClipView getFrame:&oldRightRect]; /* If the mainView itself is smaller (ie., there is some */ /* of the tiledScrollView's background showing), reduce the*/ /* size so that none of the background shows */ // if (oldMainFrame.size.height < clipFrame.size.height) // clipFrame.size.height = signalFrame.size.height; // if (oldMainFrame.size.width < clipFrame.size.width) // clipFrame.size.width = signalFrame.size.width; // [signalClipView setFrame:&clipFrame]; // clipFrame.origin.x = 0; // clipFrame.size.width = leftRuleFrame.size.width; // [scaleClipView setFrame:&clipFrame]; /* temporarily 'steal' the clipviews holding the rulers and the mainView */ /* - They are given back in printVisible: */ [mainPrintClipView setDocView:mainView]; [printView addSubview:mainPrintClipView]; if (bottomRuler) [printView addSubview:bottomRulerClipView]; if (topRuler) [printView addSubview:topRulerClipView]; if (leftRuler) [printView addSubview:leftRulerClipView]; if (rightRuler) { [printView addSubview:rightRulerClipView]; } if (vScroller) { [vScroller getFrame:&tempRect]; leftOffset = (tempRect.size.width+4); // 4 is the width of the borders } else leftOffset = 0; // Now resize the clipviews // subtract width of the left vertical scroller since we don't draw it tempRect = oldMainClipRect; tempRect.origin.x -= leftOffset; [mainPrintClipView setFrame:&tempRect]; tempRect = oldBottomRect; tempRect.origin.x -= leftOffset; [bottomRulerClipView setFrame:&tempRect]; tempRect = oldTopRect; tempRect.origin.x -= leftOffset; [topRulerClipView setFrame:&tempRect]; tempRect = oldLeftRect; tempRect.origin.x -= leftOffset; [leftRulerClipView setFrame:&tempRect]; tempRect = oldRightRect; tempRect.origin.x -= leftOffset; [rightRulerClipView setFrame:&tempRect]; /* scroll the views to the same position as they were in the tiledScrollView */ [mainView scrollPoint:(const NXPoint *)&mainVisiblePoint]; /* set the frame of the PrintView to be big enough to show everything */ clipFrame.origin = oldMainFrame.origin; clipFrame.origin.x = 0; clipFrame.size = oldMainClipBounds.size; clipFrame.size.height += (oldTopRect.size.height + oldBottomRect.size.height); clipFrame.size.width += (oldLeftRect.size.width + oldRightRect.size.width); [printView setFrame:&clipFrame]; return printView; } - printVisible:sender { if (rulersOn) { [window disableFlushWindow]; [self createPrintView]; [printView printPSCode:self]; // mainPrintClipView was setup in docView [self setDocView:[mainPrintClipView docView]]; // return to original views [self addSubview:[bottomRuler superview]]; [self addSubview:[topRuler superview]]; [self addSubview:[leftRuler superview]]; [self addSubview:[rightRuler superview]]; // restore old positions [[bottomRuler superview] setFrame:&oldBottomRect]; [[topRuler superview] setFrame:&oldTopRect]; [[leftRuler superview] setFrame:&oldLeftRect]; [[rightRuler superview] setFrame:&oldRightRect]; /* return the view to the origin it was at */ /* except change the scroll point slightly */ /* so that the scrollers will update correctly */ if (rulersOn) mainVisiblePoint.y += 1; else mainVisiblePoint.y -= 1; [[self docView] scrollPoint:(const NXPoint *)&mainVisiblePoint]; [window reenableFlushWindow]; } else // remove the message to superview to print the entire main view // rather than just the visible portion [[[self docView] superview] printPSCode:self]; return self; } - writeToStream:(NXStream *)stream { NXRect printRect; if (rulersOn) { [window disableFlushWindow]; [self createPrintView]; [printView getFrame:&printRect]; [printView copyPSCodeInside:(const NXRect *)&printRect to:(NXStream *)stream]; [self setDocView:[mainPrintClipView docView]]; // return to original views [self addSubview:[bottomRuler superview]]; [self addSubview:[topRuler superview]]; [self addSubview:[leftRuler superview]]; [self addSubview:[rightRuler superview]]; // restore old positions [[bottomRuler superview] setFrame:&oldBottomRect]; [[topRuler superview] setFrame:&oldTopRect]; [[leftRuler superview] setFrame:&oldLeftRect]; [[rightRuler superview] setFrame:&oldRightRect]; /* return the view to the origin it was at */ /* except change the scroll point slightly */ /* so that the scrollers will update correctly */ if (rulersOn) mainVisiblePoint.y += 1; else mainVisiblePoint.y -= 1; [[self docView] scrollPoint:(const NXPoint *)&mainVisiblePoint]; [window reenableFlushWindow]; } else { [[[self docView] superview] getBounds:&printRect]; [[[self docView] superview] copyPSCodeInside:(const NXRect *)&printRect to:(NXStream *)stream]; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.