Determine height of NSScroller in NSScrollView

I have a class derived from NSRulerView and have overriden drawHashMarksAndLabels(...). This is a vertical ruler.


I found that I need to account for the horizontal scroller being visible, dependent on the user's 'Show scroll bars:' setting in System Preferences/General.

i.e. the origin of the ruler should be displaced depending on visibility of the horizontal scroll bar.


The only way I have been able to come up with that works is something like


class LogScale : NSRulerView {
     override func drawHashMarksAndLabels(in in_rect: NSRect) {
          let scroll = self.scrollView else { return }
          let scrollHeight = visibleRect.height - scroll.contentView.visibleRect.height
          .
          .
          .
          // remainder of code follows to draw logarithmically spaced hash marks and labels
     }
}


i.e. I am measuring the change in height depending on the scroll bar being visible or not.

This seems a little obscure and I am wondering if there is any way to achieve the same result either directly from the scrollView, or possibly the NSScroller.


For now its working but I can see myself scratching my head in a few years wondering why I did it this way.

Answered by QuinceyMorris in 290963022

>>If the System Preference is set to 'Always', the bottom edge of the enclosed view is raised by the thickness of the scrollbar and the ruler marks are now incorrect - i.e. they need to be displaced by the thickness of the scroll bar.


Sorry if I'm being thickheaded here, but it seems to me that the ruler marks need to be positioned in the ruler view so that they match the corresponding position of the content in the "document" view (the view that's a subview of the NSClipView). That relationship can be uncovered by converting the coordinates of (say) the zero point in the document view to the coordinate system of the ruler view — which is a calculation you can do [specifically: have Cocoa do] without knowing anything about the size of the scrollers. All you need is to know when the relationship changes, which I assume is not itself a problem.


>> surely heights and widths of the rectangles are independent of the coordinate system


Not if the "document" view is scaled.

Are you drawing your marks and labels using the coordinate system of the ruler view? That shouldn't depend on the presence of scrollers.


Note that your code in line 4 is technically incorrect, because you are mixing the coordinate system of the ruler view with the coordinate system of the clip (content) view. It may also be factually incorrect, because the displacement of the ruler depends on the size of the accessory view rather than (or, as well as, I don't really know) the height of the horizontal scroller.

Yes - I am drawing marks/labels using the coordinate system of the ruler view.


If I have the System Preference set to 'Automatically ...', then when the horizontal scroll bar appears it is semi-transparent and there is no need to adjust the ruler marks.

If the System Preference is set to 'Always', the bottom edge of the enclosed view is raised by the thickness of the scrollbar and the ruler marks are now incorrect - i.e. they need to be displaced by the thickness of the scroll bar.


I realise the views have different coordinate systems, but surely heights and widths of the rectangles are independent of the coordinate system except in the unlikely scenario of the 2 views being on monitors with different resolutions?

Accepted Answer

>>If the System Preference is set to 'Always', the bottom edge of the enclosed view is raised by the thickness of the scrollbar and the ruler marks are now incorrect - i.e. they need to be displaced by the thickness of the scroll bar.


Sorry if I'm being thickheaded here, but it seems to me that the ruler marks need to be positioned in the ruler view so that they match the corresponding position of the content in the "document" view (the view that's a subview of the NSClipView). That relationship can be uncovered by converting the coordinates of (say) the zero point in the document view to the coordinate system of the ruler view — which is a calculation you can do [specifically: have Cocoa do] without knowing anything about the size of the scrollers. All you need is to know when the relationship changes, which I assume is not itself a problem.


>> surely heights and widths of the rectangles are independent of the coordinate system


Not if the "document" view is scaled.

I've sorted it out now. Thanks for the help.

Determine height of NSScroller in NSScrollView
 
 
Q