home *** CD-ROM | disk | FTP | other *** search
Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
- #import "draw.h"
-
- @implementation SyncScrollView
- /*
- * This subclass of ScrollView is extremely useful for programmers
- * who want some View to scroll along with a main docView. A good
- * example is a spreadsheet that wants its column and row headings
- * to scroll along with the cells in the spreadsheet itself.
- * It is actually quite simple. We simply override tile to place
- * two ClipViews with our views (rulers in this case) in them into
- * the view hierarchy, then override scrollClip:to: to update their
- * drawing origins when the docView is scrolled. We also override
- * reflectScroll: since we don't want that to apply to our little
- * ruler views, only to the main docView.
- */
-
- - setRulerClass:factoryId
- {
- if ([factoryId conformsTo:@protocol(Ruler)]) rulerClass = factoryId;
- return self;
- }
-
- - setRulerWidths:(NXCoord)horizontal :(NXCoord)vertical
- {
- horizontalRulerWidth = horizontal;
- verticalRulerWidth = vertical;
- return self;
- }
-
- - (BOOL)bothRulersAreVisible
- {
- return verticalRulerIsVisible && horizontalRulerIsVisible;
- }
-
- - (BOOL)eitherRulerIsVisible
- {
- return verticalRulerIsVisible || horizontalRulerIsVisible;
- }
-
- - (BOOL)verticalRulerIsVisible
- {
- return verticalRulerIsVisibleRV4
- - (BOOL)horizontalRulerIsVisible
- {
- return horizontalRulerIsVisible;
- }
-
- - setRulerOrigin:(RulerOrigin)origin
- {
- RulerOrigin oldRulerOrigin = rulerOrigin;
-
- rulerOrigin = origin;
- switch (origin) {
- case LowerRight:
- [[hClipRuler docView] setFlipped:YES];
- break;
- case UpperRight:
- [[hClipRuler docView] setFlipped:YES];
- case UpperLeft:
- [[vClipRuler docView] setFlipped:YES];
- case LowerLeft:
- break;
- default:
- rulerOrigin = oldRulerOrigin;
- break;
- }
-
- return self;
- }
-
- - makeRulers
- /*
- * This makes the rulers.
- * We do this lazily in case the user never asks for the rulers.
- */
- {
- View <Ruler> *ruler;
- NXRect aRect, bRect;
-
- if (!rulerClass || (!horizontalRulerWidth && !verticalRulerWidth)) return nil;
-
- if (horizontalRulerWidth) {
- [[contentView docView] getFrame:&aRect];
- NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
- hClipRuler = [[ClipView allocFromZone:[self zone]] init];
- ruler = [[rulerClass allocFromZone:[self zone]] initFrame:&bRect];
- [hClipRuler setDocView:ruler];
- }
- if (verticalRulerWidth) {
- [[contentView docView] getFrame:&aRect];
- NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
- vClipRuler = [[ClipView allocFromZone:[self zone]] init];
- ruler = [[rulerClass allocFromZone:[self zone]] initFrame:&bRect];
- [vClipRuler setDocView:ruler];
- }
- [self setRulerOrigin:rulerOrigin];
- rulersMade = 1;
-
- return self;
- }
-
- - updateRulers:(const NXRect *)rect
- {
- if (!rect) {
- if (verticalRulerIsVisible) {
- [[vClipRuler docView] hidePosition];
- }
- if (horizontalRulerIsVisible) {
- [[hClipRuler docView] hidePosition];
- }
- } else {
- if (verticalRulerIsVisible) {
- [[vClipRuler docView] showPosition:rect->origin.y :rect->origin.y + rect->size.height];
- }
- if (horizontalRulerIsVisible) {
- [[hClipRuler docView] showPosition:rect->origin.x :rect->origin.x + rect->size.width];
- }
- }
-
- return self;
- }
-
- - updateRuler
- {
- NXRect aRect, bRect;
-
- if (horizontalRulerIsVisible) {
- [[contentView docView] getFrame:&aRect];
- NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
- bRect.size.width += verticalRulerWidth;
- [[hClipRuler docView] setFrame:&bRect];
- [hClipRuler display];
- }
- if (verticalRulerIsVisible) {
- [[contentView docView] getFrame:&aRect];
- NXDivideRect(&aRect, &bRect,RV5ticalRulerWidth, NX_XMIN);
- [[vClipRuler docView] setFrame:&bRect];
- [vClipRuler display];
- }
-
- return self;
- }
-
- - (BOOL)showRuler:(BOOL)showIt isHorizontal:(BOOL)isHorizontal
- /*
- * Adds or removes a ruler from the view hierarchy.
- * Returns whether or not it succeeded in doing so.
- */
- {
- ClipView *ruler;
- BOOL isVisible;
- NXRect cRect, rRect;
-
- isVisible = isHorizontal ? horizontalRulerIsVisible : verticalRulerIsVisible;
- if ((showIt && isVisible) || (!showIt && !isVisible)) return NO;
- if (showIt && !rulersMade && ![self makeRulers]) return NO;
- ruler = isHorizontal ? hClipRuler : vClipRuler;
-
- if (!showIt && isVisible) {
- [ruler removeFromSuperview];
- if (isHorizontal) {
- horizontalRulerIsVisible = NO;
- } else {
- verticalRulerIsVisible = NO;
- }
- } else if (showIt && !isVisible && ruler) {
- [self addSubview:ruler];
- [window disableDisplay];
- [contentView getBounds:&cRect];
- [hClipRuler getBounds:&rRect];
- [hClipRuler setDrawOrigin:cRect.origin.x :rRect.origin.y];
- [vClipRuler getBounds:&rRect];
- [vClipRuler setDrawOrigin:rRect.origin.x :cRect.origin.y];
- [window reenableDisplay];
- if (isHorizontal) {
- horizontalRulerIsVisible = YES;
- } else {
- verticalRulerIsVisible = YES;
- }
- }
-
- return YES;
- }
-
- - adjustSizes
- {
- id windelegate;
- NXRect winFrame;
-
- windelegate = [window delegate];
- if ([windelegate respondsTo:@selector(windowWillResize:toSize:)]) {
- [window getFrame:&winFrame];
- [windelegate windowWillResize:window toSize:&winFrame.size];
- [window placeWindow:&winFrame];
- }
- [self resizeSubviews:(NXSize *)nil];
-
- return self;
- }
-
- - showHorizontalRuler:(BOOL)flag
- {
- if ([self showRuler:flag isHorizontal:YES]) [self adjustSizes];
- return self;
- }
-
- - showVerticalRuler:(BOOL)flag
- {
- if ([self showRuler:flag isHorizontal:NO]) [self adjustSizes];
- return self;
- }
-
- - showHideRulers:sender
- /*
- * If both rulers are visible, they are both hidden.
- * Otherwise, both rulers are made visible.
- */
- {
- BOOL resize = NO;
-
- if (verticalRulerIsVisible && horizontalRulerIsVisible) {
- resize = [self showRuler:NO isHorizontal:YES];
- resize = [self showRuler:NO isHorizontal:NO] || resize;
- } else {
- if (!horizontalRulerIsVisible) resize = [self showRuler:YES isHorizontal:YES];
- if (!verticalRulerIsVisible) resize = [self showRuler:YES isRV6zontal:NO] || resize;
- }
- if (resize) [self adjustSizes];
-
- return self;
- }
-
- /* ScrollView-specific stuff */
-
- - free
- {
- if (!horizontalRulerIsVisible) [hClipRuler free];
- if (!verticalRulerIsVisible) [vClipRuler free];
- return [super free];
- }
-
- - reflectScroll:cView
- /*
- * We only reflect scroll in the contentView, not the rulers.
- */
- {
- if (cView == hClipRuler || cView == vClipRuler) return self;
- return [super reflectScroll:cView];
- }
-
- - tile
- /*
- * Here is where we lay out the subviews of the ScrollView.
- * Note the use of NXDivideRect() to "slice off" a section of
- * a rectangle. This is useful since the two scrollers each
- * result in slicing a section off the contentView of the
- * ScrollView.
- */
- {
- NXRect aRect, bRect, cRect;
-
- [super tile];
-
- if (horizontalRulerIsVisible || verticalRulerIsVisible) {
- [contentView getFrame:&aRect];
- [[self docView] getFrame:&cRect];
- if (horizontalRulerIsVisible && hClipRuler) {
- NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
- [hClipRuler setFrame:&bRect];
- [[hClipRuler docView] sizeTo:cRect.size.width+verticalRulerWidth :bRect.size.height];
- }
- if (verticalRulerIsVisible && vClipRuler) {
- NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
- [vClipRuler setFrame:&bRect];
- [[vClipRuler docView] sizeTo:bRect.size.width :cRect.size.height];
- }
- [contentView setFrame:&aRect];
- }
-
- return self;
- }
-
- - scrollClip:(ClipView *)aClipView to:(const NXPoint *)aPoint
- /*
- * This is sent to us instead of rawScroll:.
- * We scroll the two rulers, then the clipView itself.
- */
- {
- id fr;
- NXRect rRect;
-
- if (horizontalRulerIsVisible && hClipRuler) {
- [hClipRuler getBounds:&rRect];
- rRect.origin.x = aPoint->x;
- [hClipRuler rawScroll:&(rRect.origin)];
- }
- if (verticalRulerIsVisible && vClipRuler) {
- [vClipRuler getBounds:&rRect];
- rRect.origin.y = aPoint->y;
- [vClipRuler rawScroll:&(rRect.origin)];
- }
-
- [aClipView rawScroll:aPoint];
-
- fr = [window firstResponder];
- if ([fr respondsTo:@selector(isRulerVisible)] && [fr isRulerVisible]) [fr updateRuler]; // keeps Text ruler up-to-date
-
- return self;
- }
-
- - descendantFrameChanged:sender
- /*
- * Any time the docView is resized, this method is
- * called to update the size of the rulers to be equal to
- * the size of the docView.
- */
- {
- RV7Rect aRect, bRect, cRect;
-
- [super descendantFrameChanged:sender];
- if (horizontalRulerIsVisible || verticalRulerIsVisible) {
- [contentView getFrame:&aRect];
- [[self docView] getFrame:&cRect];
- if (horizontalRulerIsVisible && hClipRuler) {
- NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
- [[hClipRuler docView] sizeTo:cRect.size.width+verticalRulerWidth :bRect.size.height];
- }
- if (verticalRulerIsVisible && vClipRuler) {
- NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
- [[vClipRuler docView] sizeTo:bRect.size.width :cRect.size.height];
- }
- }
-
- return self;
- }
-
- @end