/* NSScrollView.m View which scrolls another via a clip view. Copyright (C) 1996 Free Software Foundation, Inc. Author: Ovidiu Predescu Date: July 1997 Author: Felipe A. Rodriguez Date: October 1998 This file is part of the mySTEP Library and is provided under the terms of the GNU Library General Public License. */ #import #import #import #import #import #import #import #import #import "NSAppKitPrivate.h" // Class variables static Class __rulerViewClass = nil; @implementation NSScrollView + (void) setRulerViewClass:(Class)aClass { __rulerViewClass = aClass; } + (Class) rulerViewClass { return __rulerViewClass; } + (NSSize) contentSizeForFrameSize:(NSSize)frameSize // calc content size by hasHorizontalScroller:(BOOL)hFlag // taking into account hasVerticalScroller:(BOOL)vFlag // the border type borderType:(NSBorderType)borderType { NSSize size = frameSize; if (hFlag) // account for scroller size.height -= [NSScroller scrollerWidth]; if (vFlag) size.width -= [NSScroller scrollerWidth]; switch (borderType) { case NSLineBorder: case NSGrooveBorder: case NSBezelBorder: size.width -= 2; size.height -= 2; break; case NSNoBorder: break; } return size; } + (NSSize) frameSizeForContentSize:(NSSize)contentSize hasHorizontalScroller:(BOOL)hFlag hasVerticalScroller:(BOOL)vFlag borderType:(NSBorderType)borderType { NSSize size = contentSize; if (hFlag) // account for scroller size.height += [NSScroller scrollerWidth]; if (vFlag) size.width += [NSScroller scrollerWidth]; switch (borderType) { case NSLineBorder: size.width += 2; size.height += 2; break; case NSBezelBorder: case NSGrooveBorder: size.width += 4; size.height += 4; case NSNoBorder: break; } return size; } - (id) initWithFrame:(NSRect)rect { #if 0 NSLog(@"[NSScrollView initWithFrame]"); #endif if((self=[super initWithFrame:rect])) { [self setContentView:[[[NSClipView alloc] initWithFrame:rect] autorelease]]; // install default content view [self setLineScroll:10]; [self setPageScroll:40]; _sv.borderType = NSBezelBorder; _sv.scrollsDynamically = YES; // FIXME: register for user defaults change notifications and tile if needed (e.g. the scroller position has changed) } return self; } #if 0 - (void) dealloc; { [super dealloc]; } #endif - (void) setContentView:(NSClipView*)aView { #if 0 NSLog(@"NSScrollView setContentView:%@", aView); #endif if(_contentView == aView || aView == nil) return; if(_contentView) [_contentView removeFromSuperviewWithoutNeedingDisplay]; _contentView = aView; [self addSubview:_contentView]; if([aView documentView]) [self setDocumentView:[aView documentView]]; // set document view as needed/initialized [self tile]; } - (void) setHorizontalScroller:(NSScroller*)aScroller { if(_horizScroller == aScroller) return; if(_horizScroller != nil) [_horizScroller removeFromSuperview]; if ((_horizScroller = aScroller) != nil) { [_horizScroller setTarget:self]; [_horizScroller setAction:@selector(_doScroller:)]; } else _sv.hasHorizScroller = NO; } - (void) setHasHorizontalScroller:(BOOL)flag { if (_sv.hasHorizScroller == flag) return; if (flag) { if (_horizScroller == nil) [self setHorizontalScroller:[[[NSScroller alloc] initWithFrame:NSZeroRect] autorelease]]; [_horizScroller setControlSize:NSRegularControlSize]; [self addSubview:_horizScroller]; } else [_horizScroller removeFromSuperviewWithoutNeedingDisplay]; _sv.hasHorizScroller = flag; [self tile]; } - (void) setVerticalScroller:(NSScroller*)aScroller { if(_vertScroller == aScroller) return; if(_vertScroller != nil) [_vertScroller removeFromSuperview]; if ((_vertScroller = aScroller) != nil) { [_vertScroller setTarget:self]; [_vertScroller setAction:@selector(_doScroller:)]; } else _sv.hasVertScroller = NO; } - (void) setHasVerticalScroller:(BOOL)flag { if (_sv.hasVertScroller == flag) return; if (flag) { if (_vertScroller == nil) { // create one if not yet [self setVerticalScroller:[[[NSScroller alloc] initWithFrame:NSZeroRect ] autorelease]]; [_vertScroller setControlSize:NSRegularControlSize]; if (_contentView && [self isFlipped] != [_contentView isFlipped]) [_vertScroller setFloatValue:1]; } [self addSubview:_vertScroller]; } else [_vertScroller removeFromSuperviewWithoutNeedingDisplay]; _sv.hasVertScroller = flag; [self tile]; } - (void) setAutohidesScrollers:(BOOL)flag; { _sv.autohidesScrollers=flag; } - (BOOL) autohidesScrollers; { return _sv.autohidesScrollers; } - (BOOL) drawsBackground; { return [_contentView drawsBackground]; } - (void) setDrawsBackground:(BOOL) flag { [_contentView setDrawsBackground:flag]; if(!flag && [_contentView respondsToSelector:@selector(setCopiesOnScroll:)]) [_contentView setCopiesOnScroll:NO]; } - (void) scrollWheel:(NSEvent *)event { if (_vertScroller) [_vertScroller _scrollWheel:event]; else if (_horizScroller) [_horizScroller _scrollWheel:event]; } - (void) _doScroller:(NSScroller *)scroller // may be decoded as the NSScroller action from a NIB file - so, don't rename { // action method of NSScroller float amount=0.0; BOOL _knobMoved=NO; NSRect clipBounds = [_contentView bounds]; NSScrollerPart hitPart = [scroller hitPart]; NSRect documentRect = [_contentView documentRect]; NSPoint p; NSDebugLog (@"_doScroller: float value = %f", floatValue); switch(hitPart) { case NSScrollerIncrementLine: amount = (scroller == _horizScroller)?_horizontalLineScroll:_verticalLineScroll; break; case NSScrollerIncrementPage: // FIXME: this amount is the delta to a full page - i.e. ask the contentView for a page height amount = (scroller == _horizScroller)?_horizontalPageScroll:_verticalPageScroll; break; case NSScrollerDecrementLine: amount = -((scroller == _horizScroller)?_horizontalLineScroll:_verticalLineScroll); break; case NSScrollerDecrementPage: // FIXME: this amount is the delta to a full page - i.e. ask the contentView for a page height amount = -((scroller == _horizScroller)?_horizontalPageScroll:_verticalPageScroll); break; default: _knobMoved = YES; // still unknown } if (!_knobMoved) { // button scrolling if (scroller == _horizScroller) p = (NSPoint){NSMinX(clipBounds) + amount, NSMinY(clipBounds)}; else { if (scroller == _vertScroller) { p.x = clipBounds.origin.x; // If view is differently flipped if ([self isFlipped] != [_contentView isFlipped]) // reverse the scroll amount = -amount; // direction NSDebugLog (@"increment/decrement: amount = %f, flipped = %d", amount, [_contentView isFlipped]); p.y = clipBounds.origin.y + amount; } else return; // do nothing } } else { // knob scolling float floatValue = [scroller floatValue]; if (scroller == _horizScroller) { p.x = floatValue * (NSWidth(documentRect) - NSWidth(clipBounds)); p.y = clipBounds.origin.y; } else if (scroller == _vertScroller) { p.x = clipBounds.origin.x; if ([self isFlipped] != [_contentView isFlipped]) floatValue = 1 - floatValue; // differently flipped p.y = floatValue * (NSHeight(documentRect) - NSHeight(clipBounds)); } else return; // do nothing if unknown scroller } [_contentView scrollToPoint:p]; // scroll clipview if(_headerContentView) [_headerContentView scrollToPoint:(NSPoint){p.x, 0}]; if(!_knobMoved) [self reflectScrolledClipView:_contentView]; } - (void) reflectScrolledClipView:(NSClipView*)aClipView { NSRect documentFrame = NSZeroRect; NSRect clipViewBounds; float floatValue; float knobProportion; id documentView; BOOL hide; if(_sv.autohidingScrollers) return; // recursive call if(aClipView != _contentView) // do nothing if aClipView is not our content view return; #if 0 NSLog(@"reflectScrolledClipView: %@", self); #endif clipViewBounds = [_contentView bounds]; if((documentView = [_contentView documentView])) documentFrame = [documentView frame]; #if 0 NSLog(@" clipView %@", aClipView); NSLog(@" documentView %@", documentView); #endif if(_sv.hasVertScroller) { hide = (_sv.autohidesScrollers && documentFrame.size.height <= clipViewBounds.size.height); if([_vertScroller isHidden] != hide) { // needs to change #if 0 NSLog(@"vertScroller hidden: %d", hide); #endif [_vertScroller setHidden:hide]; _sv.autohidingScrollers=YES; [self tile]; // this will recurse! } if(!hide) { // update scroller size knobProportion = NSHeight(clipViewBounds) / NSHeight(documentFrame); floatValue = clipViewBounds.origin.y / (NSHeight(documentFrame) - NSHeight(clipViewBounds)); // scrolling moves bounds in negative direction! // if ([self isFlipped] != [_contentView isFlipped]) // floatValue = 1 - floatValue; [_vertScroller setFloatValue:floatValue knobProportion:knobProportion]; } } if(_sv.hasHorizScroller) { hide = (_sv.autohidesScrollers && documentFrame.size.width <= clipViewBounds.size.width); if([_horizScroller isHidden] != hide) { // needs to change #if 0 NSLog(@"horizScroller hidden: %d", hide); #endif [_horizScroller setHidden:hide]; _sv.autohidingScrollers=YES; [self tile]; // this may recurse! } if(!hide) { // update scroller size knobProportion = NSWidth(clipViewBounds) / NSWidth(documentFrame); floatValue = clipViewBounds.origin.x / (NSWidth(documentFrame) - NSWidth(clipViewBounds)); [_horizScroller setFloatValue:floatValue knobProportion:knobProportion]; } } _sv.autohidingScrollers=NO; } - (void) setHorizontalRulerView:(NSRulerView*)aRulerView // FIX ME { ASSIGN(_horizRuler, aRulerView); } - (void) setHasHorizontalRuler:(BOOL)flag // FIX ME { if (_sv.hasHorizRuler == flag) return; _sv.hasHorizRuler = flag; } - (void) setVerticalRulerView:(NSRulerView*)ruler // FIX ME { ASSIGN(_vertRuler, ruler); } - (void) setHasVerticalRuler:(BOOL)flag // FIX ME { if (_sv.hasVertRuler == flag) return; _sv.hasVertRuler = flag; } - (void) setRulersVisible:(BOOL)flag { [_horizRuler setHidden:!flag]; [_vertRuler setHidden:!flag]; } - (void) tile { // calculate layout: scrollers on right or bottom - headerView on top of contentView - note that we have flipped coordinates! NSRect vertScrollerRect, horizScrollerRect, contentRect; float borderThickness=0; if(!_contentView || !_window || !super_view) { // no need to tile now #if 0 NSLog(@"tiling without window %@", self); #endif return; } #if 0 NSLog(@"tile %@", self); #endif // FIXME: we should also tile the RulerViews switch (_sv.borderType) { case NSNoBorder: borderThickness = 0; break; case NSLineBorder: case NSBezelBorder: case NSGrooveBorder: borderThickness = 1; break; } contentRect.origin = (NSPoint){ borderThickness, borderThickness }; contentRect.size = [isa contentSizeForFrameSize:_bounds.size hasHorizontalScroller:NO hasVerticalScroller:NO borderType:_sv.borderType]; // default size without any scrollers if(_sv.hasHorizScroller && _horizScroller && ![_horizScroller isHidden]) { // make room for the horiz. scroller at the bottom float height=[_horizScroller frame].size.height; if(height < 1.0) height=[NSScroller scrollerWidthForControlSize:[_horizScroller controlSize]]; horizScrollerRect.size.height = height; // adjust for scroller height contentRect.size.height -= horizScrollerRect.size.height; } else horizScrollerRect.size.height=0.0; if(_sv.hasVertScroller && _vertScroller && ![_vertScroller isHidden]) { // make room on the right or left side BOOL scrollerLeftPosition=[[[NSUserDefaults standardUserDefaults] stringForKey:@"NSScrollerPosition"] isEqualToString:@"left"]; float width=[_vertScroller frame].size.width; if(width < 1.0) width=[NSScroller scrollerWidthForControlSize:[_vertScroller controlSize]]; contentRect.size.width -= width; // adjust for scroller width vertScrollerRect.origin.x = NSMaxX(contentRect); // to the right vertScrollerRect.origin.y = NSMinY(contentRect); vertScrollerRect.size.width = _bounds.size.width - borderThickness - vertScrollerRect.origin.x; // what remains vertScrollerRect.size.height = contentRect.size.height; // same height if(scrollerLeftPosition) { // move vertical scrollers to the left side contentRect.origin.x += vertScrollerRect.size.width; vertScrollerRect.origin.x = 0.0; // to the left } } else vertScrollerRect=NSZeroRect; if(_sv.hasHorizScroller) { horizScrollerRect.origin.x = NSMinX(contentRect); horizScrollerRect.origin.y = NSMaxY(contentRect) + borderThickness; // position below horizScrollerRect.size.width = contentRect.size.width; // horizScrollerRect.size.height = horizScrollerRect.origin.y - contentRect.origin.y; // what remains } if(_headerContentView) { // make as wide as the content view - shrink content view and vertical scroller to make room for the corner view float h = NSHeight([_headerContentView frame]); NSRect headerRect, cornerRect; contentRect.size.height -= h; // reduce height vertScrollerRect.size.height -= h; // reduce height headerRect = NSMakeRect(NSMinX(contentRect), NSMinY(contentRect), NSWidth(contentRect), h); contentRect.origin.y += h; // move down vertScrollerRect.origin.y += h; // move down if(_headerContentView && !NSEqualRects([_headerContentView frame], headerRect)) [_headerContentView setFrame:headerRect]; [_headerContentView setNeedsDisplay:YES]; if(_cornerView) { // adjust corner view to be above the vertical scroller cornerRect=NSMakeRect(NSMinX(vertScrollerRect), NSMinY(vertScrollerRect), NSWidth(vertScrollerRect), h); // may result in zero size if(!NSEqualRects([_cornerView frame], cornerRect)) [_cornerView setFrame:cornerRect]; [_cornerView setNeedsDisplay:YES]; } } if(_sv.hasHorizScroller && _horizScroller && !NSEqualRects([_horizScroller frame], horizScrollerRect)) { [_horizScroller setFrame:horizScrollerRect]; [_horizScroller setNeedsDisplay:YES]; } if(_sv.hasVertScroller && _vertScroller && !NSEqualRects([_vertScroller frame], vertScrollerRect)) { [_vertScroller setFrame:vertScrollerRect]; [_vertScroller setNeedsDisplay:YES]; } #if 0 NSLog(@"resizing contentView to frame %@", NSStringFromRect(contentRect)); #endif if(!NSEqualRects([_contentView frame], contentRect)) [_contentView setFrame:contentRect]; // this may recurse if scrollers are auto-hidden/unhidden [_contentView setNeedsDisplay:YES]; // mark as dirty } - (void) viewDidMoveToWindow; { [self tile]; } - (void) viewDidMoveToSuperView; { [self tile]; } - (void) drawRect:(NSRect)rect { float borderThickness = 0; #if 0 NSLog(@"NSScrollView drawRect: %@", NSStringFromRect(rect)); #endif switch (_sv.borderType) { // FIXME: this does not match tiling calculations and visual expectations case NSLineBorder: { borderThickness = 1; NSFrameRect (rect); break; } case NSBezelBorder: { float grays[] = { NSWhite, NSWhite, NSDarkGray, NSDarkGray, NSLightGray, NSLightGray, NSBlack, NSBlack }; NSDrawTiledRects(rect, rect, BEZEL_EDGES_NORMAL, grays, 8); borderThickness = 2; break; } case NSGrooveBorder: { NSRectEdge edges[] = {NSMinXEdge,NSMaxYEdge,NSMinXEdge,NSMaxYEdge, NSMaxXEdge,NSMinYEdge,NSMaxXEdge,NSMinYEdge}; float grays[] = { NSDarkGray, NSDarkGray, NSWhite, NSWhite, NSWhite, NSWhite, NSDarkGray, NSDarkGray }; NSDrawTiledRects(rect, rect, edges, grays, 8); borderThickness = 2; break; } case NSNoBorder: break; } // headerView, cornerView and documentView are drawn as normal subviews (if available) } - (NSRect) documentVisibleRect { return [_contentView documentVisibleRect]; } - (void) setBackgroundColor:(NSColor*)aColor { [_contentView setBackgroundColor:aColor]; // handle all background by clipview } - (void) setDocumentView:(NSView*)aView { #if 0 NSLog(@"NSScrollView setDocumentView:%@ _contentView=%@", aView, _contentView); #endif if([_contentView documentView] == aView) return; // no change if(aView && [aView respondsToSelector:@selector(headerView)]) { // peek from document view (e.g. NSTableView) NSTableHeaderView *header = [(NSTableView*)aView headerView]; if(header) { // really provides a header view NSRect rect = {{0,0},[header frame].size}; if(_headerContentView) [_headerContentView removeFromSuperviewWithoutNeedingDisplay]; _headerContentView = [[NSClipView alloc] initWithFrame:rect]; [_headerContentView setDocumentView:header]; [self addSubview:_headerContentView]; } } if(aView && [aView respondsToSelector:@selector(cornerView)]) { // peek from document view (e.g. NSTableView) if(_cornerView) [_cornerView removeFromSuperviewWithoutNeedingDisplay]; _cornerView = [(NSTableView*)aView cornerView]; if(_cornerView) [self addSubview:_cornerView]; } [_contentView setDocumentView:aView]; if(_contentView && [self isFlipped] != [_contentView isFlipped]) [_vertScroller setFloatValue:1]; [self tile]; [self reflectScrolledClipView:(NSClipView*)_contentView]; // update scroller } - (void) setFrame:(NSRect) rect { NSDebugLog (@"NSScrollView setFrame "); if(NSEqualRects(rect, _frame)) return; // ignore unchanged frame [super setFrame:rect]; [self tile]; // this will setFrame for all our subviews } - (void) setFrameSize:(NSSize) size { NSDebugLog (@"NSScrollView setFrameSize "); if(NSEqualSizes(size, _frame.size)) return; // ignore unchanged size [super setFrameSize:size]; [self tile]; // this will setFrame for all our subviews } - (void) resizeSubviewsWithOldSize:(NSSize) size { NSDebugLog (@"NSScrollView resizeSubviewsWithOldSize "); if(NSEqualSizes(size, _frame.size)) return; // ignore unchanged size [self tile]; // this will setFrame for all our subviews } // experimental to handle new navigation ideas - (NSView *) hitTest:(NSPoint)aPoint { NSEvent *event=[NSApp currentEvent]; if([event type] == NSLeftMouseDown && [event clickCount] == 2) { // decode long press on second click NSDate *limit=[NSDate dateWithTimeIntervalSinceNow:0.3]; while(YES) { event = [NSApp nextEventMatchingMask:GSTrackingLoopMask untilDate:limit inMode:NSEventTrackingRunLoopMode dequeue:NO]; // if mouse moved but not very far away, continue loop break; } if(event == nil) { // timed out before we got the next event _sv.doubleLongClick=YES; NSLog(@"NSScrollView doubleLongClick"); return self; } } _sv.doubleLongClick=NO; return [super hitTest:aPoint]; } - (void) _doubleLongClick:(NSEvent *) event; { // grab&drag NSPoint last = [self convertPoint:[event locationInWindow] fromView:nil]; NSRect clipBounds = [_contentView bounds]; NSTimeInterval lastTime = [event timestamp]; [[NSCursor pointingHandCursor] push]; while(YES) { int type=[event type]; if(type == NSLeftMouseUp) // loop until mouse goes up break; if(type == NSLeftMouseDragged) { // drag image NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil]; NSTimeInterval thisTime = [event timestamp]; NSTimeInterval deltaTime = thisTime-lastTime; NSSize velocity = (NSSize){ (p.x-last.x)/deltaTime, (p.y-last.y)/deltaTime }; // can be used to smooth movements or continue after mouse-up lastTime=thisTime; #if 0 NSLog(@"NSControl mouseDown point=%@", NSStringFromPoint(p)); #endif clipBounds.origin.x -= p.x-last.x; clipBounds.origin.y -= p.y-last.y; [_contentView scrollToPoint:clipBounds.origin]; if(_headerContentView) [_headerContentView scrollToPoint:(NSPoint){clipBounds.origin.x, 0}]; [self reflectScrolledClipView:_contentView]; last=p; } event = [NSApp nextEventMatchingMask:GSTrackingLoopMask untilDate:[NSDate distantFuture] // get next event inMode:NSEventTrackingRunLoopMode dequeue:YES]; } [NSCursor pop]; } - (void) mouseDown:(NSEvent *) event; { if(_sv.doubleLongClick) { [self _doubleLongClick:event]; _sv.doubleLongClick=NO; // has been recognized as such } else [super mouseDown:event]; } - (NSColor *) backgroundColor { return [_contentView backgroundColor]; } - (NSSize) contentSize { return [_contentView bounds].size; } - (NSClipView *) contentView { return _contentView; } - (id) documentView { return [_contentView documentView]; } - (NSCursor *) documentCursor { return [_contentView documentCursor]; } - (void) setDocumentCursor:(NSCursor*)aCursor { [_contentView setDocumentCursor:aCursor]; } - (void) setBorderType:(NSBorderType)type { _sv.borderType = type; } - (NSBorderType) borderType { return _sv.borderType; } - (NSScroller*) horizontalScroller { return _horizScroller; } - (NSScroller*) verticalScroller { return _vertScroller; } - (BOOL) hasVerticalScroller { return _sv.hasVertScroller; } - (BOOL) hasHorizontalScroller { return _sv.hasHorizScroller; } - (BOOL) hasHorizontalRuler { return _sv.hasHorizRuler; } - (BOOL) hasVerticalRuler { return _sv.hasVertRuler; } - (BOOL) rulersVisible { return _horizRuler && ![_horizRuler isHidden]; } - (NSRulerView*) horizontalRulerView { return _horizRuler; } - (NSRulerView*) verticalRulerView { return _vertRuler; } - (void) setHorizontalLineScroll:(float)aFloat { _horizontalLineScroll = aFloat; } - (void) setHorizontalPageScroll:(float)aFloat { _horizontalPageScroll = aFloat; } - (void) setVerticalLineScroll:(float)aFloat { _verticalLineScroll = aFloat; } - (void) setVerticalPageScroll:(float)aFloat { _verticalPageScroll = aFloat; } - (void) setLineScroll:(float)aFloat { [self setHorizontalLineScroll:aFloat]; [self setVerticalLineScroll:aFloat]; } // doc says we call these methods - (void) setPageScroll:(float)aFloat { [self setHorizontalPageScroll:aFloat]; [self setVerticalPageScroll:aFloat]; } - (float) horizontalPageScroll { return _horizontalPageScroll; } - (float) horizontalLineScroll { return _horizontalLineScroll; } - (float) verticalPageScroll { return _verticalPageScroll; } - (float) verticalLineScroll { return _verticalLineScroll; } - (float) pageScroll { return [self verticalPageScroll]; } - (float) lineScroll { return [self verticalLineScroll]; } - (void) setScrollsDynamically:(BOOL)flag { _sv.scrollsDynamically = flag; } - (BOOL) scrollsDynamically { return _sv.scrollsDynamically; } - (BOOL) isOpaque { return YES; } - (BOOL) isFlipped { return YES; } // compatibility - (void) mouseUp:(NSEvent *)event // called when mouse goes { // up in scroller. if(_headerContentView) [_window invalidateCursorRectsForView:[_headerContentView documentView]]; } - (void) encodeWithCoder: (NSCoder *)aCoder // NSCoding protocol { [super encodeWithCoder:aCoder]; } - (id) initWithCoder: (NSCoder *)aDecoder { self=[super initWithCoder:aDecoder]; // will call initWithFrame if([aDecoder allowsKeyedCoding]) { int sFlags=[aDecoder decodeInt32ForKey:@"NSsFlags"]; _horizScroller=[[aDecoder decodeObjectForKey:@"NSHScroller"] retain]; _vertScroller=[[aDecoder decodeObjectForKey:@"NSVScroller"] retain]; #define BORDERTYPE ((sFlags&0x0003) >> 0) _sv.borderType=BORDERTYPE; #define VSCROLLER ((sFlags&0x0010) != 0) [self setHasVerticalScroller:VSCROLLER]; #define HSCROLLER ((sFlags&0x0020) != 0) [self setHasHorizontalScroller:HSCROLLER]; #define AUTOHIDE ((sFlags&0x0200) != 0) _sv.autohidesScrollers=AUTOHIDE; #if 0 NSLog(@"%@ initWithCoder:%@ sFlags=%08x", self, aDecoder, sFlags); #endif _cornerView=[[aDecoder decodeObjectForKey:@"NSCornerView"] retain]; // if we have one... _headerContentView=[[aDecoder decodeObjectForKey:@"NSHeaderClipView"] retain]; // if we have one... #if 0 NSLog(@"corner view=%@", [_cornerView _descriptionWithSubviews]); // not embedded in a NSClipView NSLog(@"header view=%@", [_headerContentView _descriptionWithSubviews]); // this is a NSClipView which embeds the real header view #endif if([aDecoder containsValueForKey:@"NSScrollAmts"]) { struct _AMTS { NSSwappedFloat hline, vline, hpage, vpage; } *amts; unsigned len=0; amts=(struct _AMTS *) [aDecoder decodeBytesForKey:@"NSScrollAmts" returnedLength:&len]; if(len != sizeof(*amts)) NSLog(@"scroll amts=%p[%u]", amts, len); else { // byte swap from bigendian to host byte order // FIXME: really? #if 0 _horizontalLineScroll=NSSwapBigFloatToHost(amts->hline); _verticalLineScroll=NSSwapBigFloatToHost(amts->vline); _horizontalPageScroll=NSSwapBigFloatToHost(amts->hpage); _verticalPageScroll=NSSwapBigFloatToHost(amts->vpage); #endif } } [self setContentView:[aDecoder decodeObjectForKey:@"NSContentView"]]; // _contentView = [[aDecoder decodeObjectForKey:@"NSContentView"] retain]; // should load content and document view if([aDecoder containsValueForKey:@"NSDrawsBackground"]) [self setDrawsBackground:[aDecoder decodeBoolForKey:@"NSDrawsBackground"]]; // CHECKME: is this a property of the scrollview or the content view? #if 0 NSLog(@"%@ initWithCoder:%@ sFlags=%08x", self, aDecoder, sFlags); #endif } return self; } @end /* NSScrollView */