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.