Search code examples
objective-cmacosinterface-builderikimageview

IKImageView and scroll bars


I'm trying to use the IKImageViewDemo provided by apple (http://developer.apple.com/mac/library/samplecode/IKImageViewDemo/index.html) and I'm trying to add scrollbars to it. I've tried two things:

1) embedding the IKImageView in a ScrollView. This had all sorts of weird effects, like the image was no longer located where it should have been, and the scrollbars seemed to be in a fixed place, no matter how big the window was (So I could shrink the window and lose the scrollbars, even though the scrollview was set to resize with the window)

2) I added [_imageView setHasHorizontalScrollers: YES] (and vertical) into the code in the openImageURL method. This appears to have done nothing.

Am I missing something obvious?

Additionally: Why does

NSLog(@"scrollbar? H %d V %d hide %d", 
      _imageView.hasHorizontalScroller, 
      _imageView.hasVerticalScroller,
      _imageView.autohidesScrollers);

_imageView.hasHorizontalScroller = YES;
_imageView.hasVerticalScroller = YES;
_imageView.autohidesScrollers = YES;

NSLog(@"scrollbar? H %d V %d hide %d", 
      _imageView.hasHorizontalScroller, 
      _imageView.hasVerticalScroller,
      _imageView.autohidesScrollers);

give me:

scrollbar? H 0 V 0 hide 0
scrollbar? H 0 V 0 hide 0

?

Additionally additionally:

Equivalently why does:

 BOOL b = _imageView.autohidesScrollers = YES;
 NSLog (@"b %d scrollers %d", b, _imageView.autohidesScrollers);

print b 1 scrollers 0 ?


Solution

  • One thing that may have been catching you up in IKImageViewDemo was that the image was zoomed to fit in the windowDidResize: method ([_imageView zoomImageToFit: self]).

    Embedding the IKImageView in a NSScrollView is the right thing to do. In order to get the scrollbars to follow the window as you resize it, you need to adjust the springs and struts (== autoresizing mask) in Interface Builder.

    Addendum: As you've noticed, there is a bug in Mac OS X 10.6 that causes this not to work properly. You can work around the problem by subclassing the NSScrollView as follows:

    @interface IKImageClipView : NSClipView
    - (NSRect)docRect;
    @end
    
    @implementation ScrollViewWorkaround
    
    - (void)reflectScrolledClipView:(NSClipView *)cView;
    {
        NSView *_imageView = [self documentView];
        [super reflectScrolledClipView:cView];
        if ([_imageView isKindOfClass:[IKImageView class]] &&
             [[self contentView] isKindOfClass:[IKImageClipView class]] &&
             [[self contentView] respondsToSelector:@selector(docRect)]) {
            NSSize docSize = [(IKImageClipView *)[self contentView] docRect].size;
            NSSize scrollViewSize = [self contentSize];
            // NSLog(@"doc %@ scrollView %@", NSStringFromSize(docSize), NSStringFromSize(scrollViewSize));
            if (docSize.height > scrollViewSize.height || docSize.width > scrollViewSize.width)
             ((IKImageView *)_imageView).autohidesScrollers = NO;
            else
             ((IKImageView *)_imageView).autohidesScrollers = YES;
        }
    }
    
    @end
    

    Try this out:

    http://dl.dropbox.com/u/1583683/IKImageViewDemo.zip

    It's a version of IKImageViewDemo with scroll bars and the above workaround.