Search code examples
objective-ccocoansscrollview

How to pass scrolling input to a different view


This site really is awesome.

I have what is hopefully a simple question this time. I would like to pass any scrolling input from the user (could be wheel, touchpad, etc) to an NSScrollView which contains my own subviews.

At the moment if the user scrolls just on the documentView (outside of my subviews' frames) the scroll works normally but if they scroll while the cursor is over a subview nothing happens. So basically I'd like to have the subview recognise the scroll event and pass it back to the scroll view.

Any help is greatly appreciated.

Cheers.

EDIT: Here is the code I'm using to add the subviews to the documentView _milestoneView and _activityView are both NSView subclasses which have a corresponding nib (created with instantiateNibWithOwner and objects hooked up accordingly) they contain a NSTextField, PXListView and some have a NSProgressIndicator.

-(void)useProject:(NSNumber *)projectId
{
[self resetView];

NSRect bounds = [[self view] bounds];
NSRect defaultFrame = NSMakeRect(20, NSMaxY(bounds)-93, NSMaxX(bounds)-20, 50);


//Prepare the milestone view
if (_milestoneView == nil)
    _milestoneView = [MilestoneView milestoneViewFromNibWithFrame:defaultFrame withProject:[BCLocalFetch projectForId:projectId]];
[_milestoneView reloadList];


//Prepare the activity view
if (_activityView == nil)
    _activityView = [ActivityView activityViewFromNibWithFrame:defaultFrame withProject:[BCLocalFetch projectForId:projectId]];

[self refresh];
}

I then use the refresh method to reposition them as the content sizes vary so I wanted to have a separate method.

-(void)refresh
{
//Position the milestones first
[_milestoneView setFrameOrigin:NSMakePoint(20, NSMaxY([[self view] bounds])-[_milestoneView frame].size.height-60)];
if ([[_milestoneView milestones] count] > 0)
    [[self view] addSubview:_milestoneView];

//Now the activity view
[_activityView setFrameOrigin:NSMakePoint(20, [_milestoneView frame].origin.y-[_activityView frame].size.height-20)];
[[self view] addSubview:_activityView];

[self autosizeView];
}

-(void)autosizeView
{
//Resize the view to accommodate all subviews
NSRect oldFrame = [[self view] frame];
CGFloat lastY = [_activityView frame].origin.y;
if (lastY < 0) {
    CGFloat newHeight = oldFrame.size.height + (-lastY);
    [[self view] setFrameSize:NSMakeSize(oldFrame.size.width, newHeight)];
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"BBContentDidResizeNotification" object:self];
}

Solution

  • Ok so I came back to the issue and finally got it worked out. The implementation was actually quite simple. I added a property to PXListView to point to the NSScrollView that is to be scrolled. I then implemented NSResponder's scrollWheel: method like this:

    -(void)scrollWheel:(NSEvent *)theEvent
    {
        //Pass scrolling to the superview
        [_scrollHandler scrollWheel:theEvent];
    }
    

    And all is well!