Annotation of Examples/AppKit/Draw/SyncScrollView.m, revision 1.1

1.1     ! root        1: #import "draw.h"
        !             2: 
        !             3: @implementation SyncScrollView
        !             4: /*
        !             5:  * This subclass of ScrollView is extremely useful for programmers
        !             6:  * who want some View to scroll along with a main docView.  A good
        !             7:  * example is a spreadsheet that wants its column and row headings
        !             8:  * to scroll along with the cells in the spreadsheet itself.
        !             9:  * It is actually quite simple.  We simply override tile to place
        !            10:  * two ClipViews with our views (rulers in this case) in them into
        !            11:  * the view hierarchy, then override scrollClip:to: to update their
        !            12:  * drawing origins when the docView is scrolled.  We also override
        !            13:  * reflectScroll: since we don't want that to apply to our little
        !            14:  * ruler views, only to the main docView.
        !            15:  */
        !            16: 
        !            17: - setRulerClass:factoryId
        !            18: {
        !            19:     if ([factoryId conformsTo:@protocol(Ruler)]) rulerClass = factoryId;
        !            20:     return self;
        !            21: }
        !            22: 
        !            23: - setRulerWidths:(NXCoord)horizontal :(NXCoord)vertical
        !            24: {
        !            25:     horizontalRulerWidth = horizontal;
        !            26:     verticalRulerWidth = vertical;
        !            27:     return self;
        !            28: }
        !            29: 
        !            30: - (BOOL)bothRulersAreVisible
        !            31: {
        !            32:     return verticalRulerIsVisible && horizontalRulerIsVisible;
        !            33: }
        !            34: 
        !            35: - (BOOL)eitherRulerIsVisible
        !            36: {
        !            37:     return verticalRulerIsVisible || horizontalRulerIsVisible;
        !            38: }
        !            39: 
        !            40: - (BOOL)verticalRulerIsVisible
        !            41: {
        !            42:     return verticalRulerIsVisible;
        !            43: }
        !            44: 
        !            45: - (BOOL)horizontalRulerIsVisible
        !            46: {
        !            47:     return horizontalRulerIsVisible;
        !            48: }
        !            49: 
        !            50: - setRulerOrigin:(RulerOrigin)origin
        !            51: {
        !            52:     RulerOrigin oldRulerOrigin = rulerOrigin;
        !            53: 
        !            54:     rulerOrigin = origin;
        !            55:     switch (origin) {
        !            56:        case LowerRight:
        !            57:            [[hClipRuler docView] setFlipped:YES];
        !            58:            break;
        !            59:        case UpperRight:
        !            60:            [[hClipRuler docView] setFlipped:YES];
        !            61:        case UpperLeft:
        !            62:            [[vClipRuler docView] setFlipped:YES];
        !            63:        case LowerLeft:
        !            64:            break;
        !            65:        default:
        !            66:            rulerOrigin = oldRulerOrigin;
        !            67:            break;
        !            68:     }
        !            69: 
        !            70:     return self;
        !            71: }
        !            72: 
        !            73: - makeRulers
        !            74: /*
        !            75:  * This makes the rulers.
        !            76:  * We do this lazily in case the user never asks for the rulers.
        !            77:  */
        !            78: {
        !            79:     View <Ruler> *ruler;
        !            80:     NXRect aRect, bRect;
        !            81: 
        !            82:     if (!rulerClass || (!horizontalRulerWidth && !verticalRulerWidth)) return nil;
        !            83: 
        !            84:     if (horizontalRulerWidth) {
        !            85:        [[contentView docView] getFrame:&aRect];
        !            86:        NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
        !            87:        hClipRuler = [[ClipView allocFromZone:[self zone]] init];
        !            88:        ruler = [[rulerClass allocFromZone:[self zone]] initFrame:&bRect];
        !            89:        [hClipRuler setDocView:ruler];
        !            90:     }
        !            91:     if (verticalRulerWidth) {
        !            92:        [[contentView docView] getFrame:&aRect];
        !            93:        NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
        !            94:        vClipRuler = [[ClipView allocFromZone:[self zone]] init];
        !            95:        ruler = [[rulerClass allocFromZone:[self zone]] initFrame:&bRect];
        !            96:        [vClipRuler setDocView:ruler];
        !            97:     }
        !            98:     [self setRulerOrigin:rulerOrigin];
        !            99:     rulersMade = 1;
        !           100: 
        !           101:     return self;
        !           102: }
        !           103: 
        !           104: - updateRulers:(const NXRect *)rect
        !           105: {
        !           106:     if (!rect) {
        !           107:        if (verticalRulerIsVisible) {
        !           108:            [[vClipRuler docView] hidePosition];
        !           109:        }
        !           110:        if (horizontalRulerIsVisible) {
        !           111:            [[hClipRuler docView] hidePosition];
        !           112:        }
        !           113:     } else {
        !           114:        if (verticalRulerIsVisible) {
        !           115:            [[vClipRuler docView] showPosition:rect->origin.y :rect->origin.y + rect->size.height];
        !           116:        }
        !           117:        if (horizontalRulerIsVisible) {
        !           118:            [[hClipRuler docView] showPosition:rect->origin.x :rect->origin.x + rect->size.width];
        !           119:        }
        !           120:     }
        !           121: 
        !           122:     return self;
        !           123: }
        !           124: 
        !           125: - updateRuler
        !           126: {
        !           127:     NXRect aRect, bRect;
        !           128: 
        !           129:     if (horizontalRulerIsVisible) {
        !           130:        [[contentView docView] getFrame:&aRect];
        !           131:        NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
        !           132:        bRect.size.width += verticalRulerWidth;
        !           133:        [[hClipRuler docView] setFrame:&bRect];
        !           134:        [hClipRuler display];
        !           135:     }
        !           136:     if (verticalRulerIsVisible) {
        !           137:        [[contentView docView] getFrame:&aRect];
        !           138:        NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
        !           139:        [[vClipRuler docView] setFrame:&bRect];
        !           140:        [vClipRuler display];
        !           141:     }
        !           142: 
        !           143:     return self;
        !           144: }
        !           145: 
        !           146: - (BOOL)showRuler:(BOOL)showIt isHorizontal:(BOOL)isHorizontal
        !           147: /*
        !           148:  * Adds or removes a ruler from the view hierarchy.
        !           149:  * Returns whether or not it succeeded in doing so.
        !           150:  */
        !           151: {
        !           152:     ClipView *ruler;
        !           153:     BOOL isVisible;
        !           154:     NXRect cRect, rRect;
        !           155: 
        !           156:     isVisible = isHorizontal ? horizontalRulerIsVisible : verticalRulerIsVisible;
        !           157:     if ((showIt && isVisible) || (!showIt && !isVisible)) return NO;
        !           158:     if (showIt && !rulersMade && ![self makeRulers]) return NO;
        !           159:     ruler = isHorizontal ? hClipRuler : vClipRuler;
        !           160: 
        !           161:     if (!showIt && isVisible) {
        !           162:        [ruler removeFromSuperview];
        !           163:        if (isHorizontal) {
        !           164:            horizontalRulerIsVisible = NO;
        !           165:        } else {
        !           166:            verticalRulerIsVisible = NO;
        !           167:        }
        !           168:     } else if (showIt && !isVisible && ruler) {
        !           169:        [self addSubview:ruler];
        !           170:        [window disableDisplay];
        !           171:        [contentView getBounds:&cRect];
        !           172:        [hClipRuler getBounds:&rRect];
        !           173:        [hClipRuler setDrawOrigin:cRect.origin.x :rRect.origin.y];
        !           174:        [vClipRuler getBounds:&rRect];
        !           175:        [vClipRuler setDrawOrigin:rRect.origin.x :cRect.origin.y];
        !           176:        [window reenableDisplay];
        !           177:        if (isHorizontal) {
        !           178:            horizontalRulerIsVisible = YES;
        !           179:        } else {
        !           180:            verticalRulerIsVisible = YES;
        !           181:        }
        !           182:     }
        !           183: 
        !           184:     return YES;
        !           185: }
        !           186: 
        !           187: - adjustSizes
        !           188: {
        !           189:     id windelegate;
        !           190:     NXRect winFrame;
        !           191: 
        !           192:     windelegate = [window delegate];
        !           193:     if ([windelegate respondsTo:@selector(windowWillResize:toSize:)]) {
        !           194:        [window getFrame:&winFrame];
        !           195:        [windelegate windowWillResize:window toSize:&winFrame.size];
        !           196:        [window placeWindow:&winFrame];
        !           197:     }
        !           198:     [self resizeSubviews:(NXSize *)nil];
        !           199: 
        !           200:     return self;
        !           201: }
        !           202: 
        !           203: - showHorizontalRuler:(BOOL)flag
        !           204: {
        !           205:     if ([self showRuler:flag isHorizontal:YES]) [self adjustSizes];
        !           206:     return self;
        !           207: }
        !           208: 
        !           209: - showVerticalRuler:(BOOL)flag
        !           210: {
        !           211:     if ([self showRuler:flag isHorizontal:NO]) [self adjustSizes];
        !           212:     return self;
        !           213: }
        !           214: 
        !           215: - showHideRulers:sender
        !           216: /*
        !           217:  * If both rulers are visible, they are both hidden.
        !           218:  * Otherwise, both rulers are made visible.
        !           219:  */
        !           220: {
        !           221:     BOOL resize = NO;
        !           222: 
        !           223:     if (verticalRulerIsVisible && horizontalRulerIsVisible) {
        !           224:        resize = [self showRuler:NO isHorizontal:YES];
        !           225:        resize = [self showRuler:NO isHorizontal:NO] || resize;
        !           226:     } else {
        !           227:        if (!horizontalRulerIsVisible) resize = [self showRuler:YES isHorizontal:YES];
        !           228:        if (!verticalRulerIsVisible) resize = [self showRuler:YES isHorizontal:NO] || resize;
        !           229:     }
        !           230:     if (resize) [self adjustSizes];
        !           231: 
        !           232:     return self;
        !           233: }
        !           234: 
        !           235: /* ScrollView-specific stuff */
        !           236: 
        !           237: - free
        !           238: {
        !           239:     if (!horizontalRulerIsVisible) [hClipRuler free];
        !           240:     if (!verticalRulerIsVisible) [vClipRuler free];
        !           241:     return [super free];    
        !           242: }
        !           243: 
        !           244: - reflectScroll:cView
        !           245: /*
        !           246:  * We only reflect scroll in the contentView, not the rulers.
        !           247:  */
        !           248: {
        !           249:     if (cView == hClipRuler || cView == vClipRuler) return self;
        !           250:     return [super reflectScroll:cView];
        !           251: }
        !           252: 
        !           253: - tile
        !           254: /*
        !           255:  * Here is where we lay out the subviews of the ScrollView.
        !           256:  * Note the use of NXDivideRect() to "slice off" a section of
        !           257:  * a rectangle.  This is useful since the two scrollers each
        !           258:  * result in slicing a section off the contentView of the
        !           259:  * ScrollView.
        !           260:  */
        !           261: {
        !           262:     NXRect aRect, bRect, cRect;
        !           263: 
        !           264:     [super tile];
        !           265: 
        !           266:     if (horizontalRulerIsVisible || verticalRulerIsVisible) {
        !           267:        [contentView getFrame:&aRect];
        !           268:        [[self docView] getFrame:&cRect];
        !           269:        if (horizontalRulerIsVisible && hClipRuler) {
        !           270:            NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
        !           271:            [hClipRuler setFrame:&bRect];
        !           272:            [[hClipRuler docView] sizeTo:cRect.size.width+verticalRulerWidth :bRect.size.height];
        !           273:        }
        !           274:        if (verticalRulerIsVisible && vClipRuler) {
        !           275:            NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
        !           276:            [vClipRuler setFrame:&bRect];
        !           277:            [[vClipRuler docView] sizeTo:bRect.size.width :cRect.size.height];
        !           278:        }
        !           279:        [contentView setFrame:&aRect];
        !           280:     }
        !           281: 
        !           282:     return self;
        !           283: }
        !           284: 
        !           285: - scrollClip:(ClipView *)aClipView to:(const NXPoint *)aPoint
        !           286: /*
        !           287:  * This is sent to us instead of rawScroll:.
        !           288:  * We scroll the two rulers, then the clipView itself.
        !           289:  */
        !           290: {
        !           291:     id fr;
        !           292:     NXRect rRect;
        !           293: 
        !           294:     if (horizontalRulerIsVisible && hClipRuler) {
        !           295:        [hClipRuler getBounds:&rRect];
        !           296:        rRect.origin.x = aPoint->x;
        !           297:        [hClipRuler rawScroll:&(rRect.origin)];
        !           298:     }
        !           299:     if (verticalRulerIsVisible && vClipRuler) {
        !           300:        [vClipRuler getBounds:&rRect];
        !           301:        rRect.origin.y = aPoint->y;
        !           302:        [vClipRuler rawScroll:&(rRect.origin)];
        !           303:     }
        !           304: 
        !           305:     [aClipView rawScroll:aPoint];
        !           306: 
        !           307:     fr = [window firstResponder];
        !           308:     if ([fr respondsTo:@selector(isRulerVisible)] && [fr isRulerVisible]) [fr updateRuler]; // keeps Text ruler up-to-date
        !           309: 
        !           310:     return self;
        !           311: }
        !           312: 
        !           313: - descendantFrameChanged:sender
        !           314: /*
        !           315:  * Any time the docView is resized, this method is
        !           316:  * called to update the size of the rulers to be equal to
        !           317:  * the size of the docView.
        !           318:  */
        !           319: {
        !           320:     NXRect aRect, bRect, cRect;
        !           321: 
        !           322:     [super descendantFrameChanged:sender];
        !           323:     if (horizontalRulerIsVisible || verticalRulerIsVisible) {
        !           324:        [contentView getFrame:&aRect];
        !           325:        [[self docView] getFrame:&cRect];
        !           326:        if (horizontalRulerIsVisible && hClipRuler) {
        !           327:            NXDivideRect(&aRect, &bRect, horizontalRulerWidth, NX_YMIN);
        !           328:            [[hClipRuler docView] sizeTo:cRect.size.width+verticalRulerWidth :bRect.size.height];
        !           329:        }
        !           330:        if (verticalRulerIsVisible && vClipRuler) {
        !           331:            NXDivideRect(&aRect, &bRect, verticalRulerWidth, NX_XMIN);
        !           332:            [[vClipRuler docView] sizeTo:bRect.size.width :cRect.size.height];
        !           333:        }
        !           334:     }
        !           335: 
        !           336:     return self;
        !           337: }
        !           338: 
        !           339: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.