View Full Version : How to zoom in NSScrollView
Mar 16, 2008, 06:25 PM
My environment is XCode 3.0 and OS-X 10.5.2, writing (almost) my first serious Objective-C app after 15+ years of code cutting and 5+ years of C#/C++/etc.
What I am trying to achieve is to display information related to the frequency of a radio which can range from 0.5MHz (can be assumed to be 0) to 500MHz. I imagine that this will be a wide but thin 'view'. Within this range there are certain 'bands' that I am more interested in than others (this is a amateur radio so I am specifically interested in the 80, 40, 20, 2 metre, 60cm band as well as others). In these 'bands' I want to display information about the various modes (AM, SSB, FM, CW...) and usage (voice, data, SSTV...).
I have tried to create an NSScrollView where the lowest view in the hierarchy holds the information and I can scroll through this horizontally. I also have a ruler at the top which I have set to show the 'frequency'. All this seems to work well.
However, I now want to be able to zoom in and out of the display so that I can 'see' a greater range of frequencies for approximate frequency selection (say a range of 50-100MHz) and then zoom in so that I can see the details more clearly (see 3-5MHz range).
I have tried to use the bounds and frame rectangle settings and I can achieve some form of zooming, but the base is always 0 and the top of the display that I can slide to reduces as I zoom in. I'm obviously doing something wrong, but I'm not sure how this should be done.
Can some kind soul please let me know how I should be going about this? Pointers and references would be appreciated. If I need a completely different approach to solving this problem then that would be OK as well (but the problem itself remains to be solved!)
Mar 16, 2008, 06:44 PM
I'm probably just being stupid, but can you attach a screenshot? I can't quite picture it.
Mar 16, 2008, 07:31 PM
Hm, NSScrollViews are used for scrolling, not zooming. Zooming isn't supported automatically, you need to implement your own method via something like NSAffineTransform.
Mar 17, 2008, 12:45 AM
EraserHead - I can't post a screenshot because I'm trying to write this (and I'm a work right now, but the development system is at home!), but I've tried to knock up an example - see attached.
What I want is to have the scrollbar (part of the NSScrollView) allow me to scan throughout the whole display range regardless of the zoom setting. The zoom setting means that, at one end, it squeezes the whole display horizontally into the screen display, while at the other end it only shows a very thin sliver but have that sliver streched fom side to side of the screen display.
Krainjow - thanks for the information and suggestion. I've tried to use the NSAffineTransform but I can't be using it correctly, as it completely messed up the display (it seemed to flip it and start filling the rectangular I'm drawing with black which was hiding the text - it also stopped any alignment with the ruler and always scrolled from the left0hand edge to a small way into the display).
Mar 17, 2008, 05:50 AM
So essentially you are having 3 scroll bars.. You could just use something like the following:
The view at the top is an NSScrollView, without scroll bars as you are controlling the position with the NSSliders the first one would be (say) 10x less sensitive than the control at the bottom.
Though this would have the disadvantage that you can't zoom in and out to see more information, but you can get additional precision.
Alternatively if you want to zoom, my feeling is that it might well be better to use NSSliders to work out what you want to display, and then let the computer choose the information and just stick it in an NSView. Though I've never done anything like this, so I'm not really sure.
Mar 17, 2008, 04:03 PM
How are you drawing the frequency graph?
Usually in frequency graphs to "zoom" you simply draw a shorter selection of the frequency graph in the current view.
If you are using a framework/library to do the drawing of the graph you should be able to provide a shorter chunk of data to draw and when you scroll you draw the next chunk.
Mar 17, 2008, 06:13 PM
May be I'm going about this all wrong if you are saying this this is not a 'usual' operation - I thought it would be as I've seen it in several apps (word processors, image editors, many spreadsheets etc.).
For example: how is this done in image editing programs. In these, the image is often bigger than the screen, and the user can zoom in and out to see a smaller section in greater detail (often to the point where individual pixels are shown as large squares).
When the zoom is far away, the whole picture is seen and the scroll bars adjust so that they hardly move at all (the slider expands to take up all of the space). When you zoom in, the sliders adjust so that they allow you to move over the whole picture surface at the higher magnification.
I guess I want to do the same thing but in only 1 dimension (horizontally - the vertical size is always the same).
How would you go about doing this?
Thanks for the assistance - its much appreciated in helping me to get my thinking more Mac/Cocoa like.
Mar 17, 2008, 08:00 PM
I haven't worked with custom views within scroll views much, so I can't tell you exactly what you have to do there, but I'm pretty sure you need to do something like setFrameSize: on your view to notify the scroll view that its document view has changed its size. So when you want to zoom in, you probably need to mathematically calculate the new width and height of your custom view depending on the zoomed in value and redraw the view using these new values.
I wrote a graphing view a while back and did something like this (although it wasn't in a scroll view). I just calculated the values needed for displaying the view at different zoom levels.
For example, at a normal zoom, let's say 10 px is 1 unit, and so then at 2x zoom 20 px is 1 unit. I think you need something like this.
Mar 18, 2008, 07:34 PM
Thanks for the help guys. I thought I had managed to get my head around the various views that make up an NSScrollView, and the frame vs bounds thing, but after playing with this for several hours last night I obviously haven't. Sigh.
I guess I'm just frustrated that something that I see happening so often in applications seems to be beyond my abilities to achieve. Sigh.
Mar 19, 2008, 06:11 AM
The way I dealt with this in the image editor I was writing was to reset the bounds of my view whenever I zoomed and maintain an internal scale factor that I drew at when requested. That way I could redraw things like grid lines further apart without them getting wider as they would on a straight zoom.