My view contains a horizontally scrolling Scroll View containing multiple vertically scrolling Table Views.
See diagram:
However, the Table Views are blocking horizontal scrolling in the Scroll View when the cursor is on them.
How can I allow the scroll to pass on to the superview?
Code for Application
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
var viewController: ViewController!
func applicationDidFinishLaunching(aNotification: NSNotification) {
viewController = ViewController(nibName: "ViewController", bundle: nil)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
window.contentView!.addSubview(viewController.view)
//...
}
//...
}
View Controller
class ViewController: NSViewController {
@IBOutlet weak var scrollView: NSScrollView!
//...
func addListView(listPath: String) {
let listView = ListViewController(nibName: "ListView", bundle: nil)
listView!.listPath = listPath
listView!.view.translatesAutoresizingMaskIntoConstraints = false
scrollView.contentView.addSubview(listView!.view)
//...
}
//...
}
List View
class ListViewController: NSViewController {
@IBOutlet weak var itemsTitleView: NSTextField!
@IBOutlet weak var itemsTableView: MyTableView!
//...
}
TableView
class MyTableView: NSTableView {
override func drawRect(dirtyRect: NSRect) {
super.drawRect(dirtyRect)
// Drawing code here.
}
var mainScrollView: NSScrollView? {
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.viewController.scrollView
}
override func mouseDown(theEvent: NSEvent) {
// do nothing
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
The first thing I would try is to catch the scroll event as it's delivered to the table view. Once you've made sure the event object represents a horizontal-scroll gesture, redirect it to the main scroll view.
class MyTableView: NSTableView {
var mainScrollView: NSScrollView? {
// Your tables will need some way to access the main scroll view.
// I'm assuming here that there's a reference to it on the AppDelegate
let app = NSApplication.sharedApplication()
let delegate = app.delegate as! AppDelegate
return delegate.mainScrollView
}
override func scrollWheel(theEvent: NSEvent) {
if theEvent.scrollingDeltaY == 0 {
// It's a horizontal scroll -> redirect it
if let tableScrollView = enclosingScrollView, mainScrollView = self.mainScrollView {
mainScrollView.scrollWheel(theEvent)
}
} else {
// It's a vertical scroll -> behave normally
super.scrollWheel(theEvent)
}
}
}
I have to say though, anytime you start messing with events like this, you need to be prepared for side-effects; in the simple demo-app I created to test this code, it seemed to work okay, but don't be surprised if this approach throws up additional challenges.