Annotation of Examples/AppKit/Draw/SyncScrollView.m, revision 1.1.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.