Adding NSScrollView to Canvas

More doing things I shouldn’t be doing, just in pursuit of a more modern feeling Mac app… Xojo really needs a way to do this already. Elastic scrolling was introduced in 10.9.

I’ve seen the piDog canvas and some examples around, and have this working pretty well. There’s one problem I haven’t been able to resolve yet. The canvas itself anchors to the bottom left because that’s where 0,0 is with NSView. Overriding the isFlipped property would probably help, but that seems impractical in Xojo. So I’m out of ideas.

Here’s the code I’m using already:

[code]Var MyView As NSViewMBS = Self.NSViewMBS
Var ContentView As NSViewMBS = MyView.Superview
Var OutsideRect As NSRectMBS = MyView.Frame

MyView.RemoveFromSuperviewWithoutNeedingDisplay
MyView.AutoresizingMask = NSViewMBS.NSViewWidthSizable

Var ScrollView As New NSScrollViewMBS(OutsideRect.X, OutsideRect.Y, OutsideRect.Width, OutsideRect.Height)
ScrollView.HasVerticalScroller = True
ScrollView.VerticalScrollElasticity = ScrollView.NSScrollElasticityAllowed
ScrollView.DocumentView = MyView
ScrollView.ContentView.ScrollToPoint(New NSPointMBS(0, 0))
ScrollView.AutoresizingMask = NSViewMBS.NSViewHeightSizable

ContentView.AddSubview(ScrollView)

Self.mMacScrollView = ScrollView
Self.mMacSelfView = MyView[/code]

I might be able to use notifications to track the height of the scroll view and break the canvas back out of the scroll view when the view height is greater than the canvas height. But that seems… terrible. I’ve also tried adding both NSViewMinYMargin and NSViewMaxYMargin in different combinations - though I think MinY would be the right one - but that didn’t seem to make a difference.

As someone whose been fighting Xojo controls in a ScrollView for years, I’d say don’t do it.

To get the contents to align to the top, you have to override NSClipView and do the math yourself, it’s not too hard if you want views aligned to the top, but if you want say views to be centered when too small or other clever things, it gets messy really quickly, especially across different macOS versions.

Overriding “isFlipped” works, but the contents of your view are then flipped, text is upside down and so are images, you can fix this in a canvas, but setting isFlipped back again, using CoreText you can also draw text upside down (so it comes out the right way up).

I have a bunch of Feedback requests, that need to be resolved before Xojo controls will work 100% in a ScrollView or NSPopover to that point. There’s even a Feedback request for a native ScrollView that’s compatible with Xojo’s co-ordinate system.

Instead what I’ve been doing (recently) is using my own fake scrollview, it looks very similar to a real scrollview, supports elastic scrolling and most importantly is compatible with Xojo’s co-ordinate system. The only downside is that the actually scrolling isn’t as smooth as a native scrollview, it’s close, but I can tell the difference.

The code is available as part of the Ohanaware App Kit, included with this years Omegabundle.

1 Like

Yeah I’ve spent time with the data from NSEvent trying to simulate the behavior, but I haven’t been able to come close. I might just stick to drawing a scroll thumb like I did in Xojo’s navigator.

You can fake an overlay scrollbar with the built-in Xojo scrollbar, it requires some Objective-C swizzling, again, it’s not perfect, but it’s close enough that the people I’ve tested it with, can’t tell the difference.

If you wanna see, take a look at https://ohanaware.com/appreport/ the sidebar uses my fake scroll view, with the hacked Xojo scrollbars. The main content is a HTML Viewer, so I didn’t have to anything for that :slight_smile:

Oof I see what you mean. It works but it’s janky. That honestly feels like a rounding error.

Do you have the code to do this? I don’t know where I’d start with this, and I’d at least like to rule out the possibility myself.