Using Auto Layout to position an NSWindow - cocoa

Is it possible to use Auto Layout to position a window on the screen?
I'd like to set up constraints to position a window relative to an NSStatusItem. I'd like the window to be centered below the NSStatusItem, but also not be partially offscreen. So, I'd need weak constraints for centering relative to the NSStatusItem and strong constraints for maintaining a minimum distance from the screen edges.
How can I accomplish this?

Auto Layout doesn't work to position windows. The layout engine works per-window to lay out views within that window.
Luckily, this particular layout problem doesn't look too difficult to accomplish the old way. Figure the frame of the window below the NSStatusItem assuming it fits. Then check to see if that frame intersects with the screen edge. If it does, nudge it to the left until it doesn't.

Related

Using autolayout, how can I center a subview in an NSSplitView without forcing the width NSSplitView to be static?

I have an NSSplitView with content in both NSViews. The left NSView has 2 constraints – Equal Widths and Equal Heights. The right NSView has something simple, say an NSTextField, which is centered via constraints Center X Alignment and Center Y Alighment. This is what I hoped it would look like as I resize the window and/or the NSSplitView divider:
This is what's happening:
I've tried a great deal of configuration changes, I've tried using an NSSplitViewController vs just dropping an NSSplitView into an NSViewController to adjust more parameters programmatically, but I'm not having any luck. Whenever resizing the window, the left view always takes over the excess space. The same happens with the divider (it can be resized, but letting go of the mouse button causes it to snap right back). It seems there's something fundamental that I'm missing here.
The text field's content hugging priority is probably higher than the split view item's holding priority. Fix that and the view should probably work the way you expect.
Also, if, when you resize the view, the left view is resizing with the window while the right view stays the same size, then that suggests that the left view's holding priority may be higher than the right's. You should make the side that you want to stay the same size have the higher holding priority.
That said, I'm not sure what you mean about the constraints you've set on the subviews. "The left NSView has 2 constraints – Equal Widths and Equal Heights." What do you mean here? Its width is equal to what? Its height is equal to what? Do you mean it has an aspect ratio constraint? Frankly, I can't think of what constraints of those kinds would make sense for a view within a split view.

How to get the size in pixels of the Resize Corners of a Window

Is there a way (API) of getting the size (vertical and horizontal) in pixels of the resize corners?
I am referring to the area at each of the corners of a window where you can resize the window in both directions (Left-to-Right and Top-to-Bottom) at the same time using your mouse. You will know you are there with your mouse cursor when you hover over the corners of the window and the mouse cursor is a Diagonal Resizing cursor.
Thank you
Edit:
An example: Hover your mouse over the right edge of a sizable window. Start in the middle (vertically) of the window and move the mouse up along the edge until the horizontal sizing cursor changes to a diagonal sizing cursor. How do I determine by asking the OS how far that position when the cursor changes, is from the top of the window.
I would suggest to use the size of the scrollbars. Call GetSystemMetrics with SM_CYHSCROLL and SM_CXVSCROLL. May be also SM_CYSIZEFRAME and SM_CXSIZEFRAME sizes can be combined.
But I think a better value is to use the height of the status bar. However even Microsoft Windows seems to use some fixed value as can seen on the screenshot.
Comparing the results of GetClientRect and GetWindowRect will tell you how wide the non-client (border) area is along each edge of the window.
If you're concerned that it might not all be active for sizing (true especially along the top), or you want to distinguish the diagonal sizing areas from edge sizing areas, you can take the coordinates discovered in step 1 and pass them to SendMessage(WM_NCHITTEST) See its documentation for the various return codes. There's no problem sending this message repeatedly -- it's designed to be called for each mouse move event and therefore is very fast.

Best way to obtain a scrollable OpenGL view with Cocoa

Say I'm writing a 2D cad program of some sort, and I want to be able to zoom in and scroll around my document. However, I also want full control over how my document is drawn and I want an OpenGL context for which to do the drawing. How do I do this? Should I subclass NSScrollView and do something I can't quite figure out there? Should I subclass NSOpenGLView and add a pair of NSScrollers and figure out how to draw them properly? Making NSScrollers and drawing them in a way that looks good natively looks nontrivial, but NSScrollViews seem to want to own all the content you might be scrolling, rather than letting me control the size of the knob of the scroll bar and other such things. I'd be completely content with giving a document size in pixels or some such, just the most important thing to me is that when I draw to (0,0) in my OpenGL context, I draw to the corner of the window, and not into some buffer that NSScrollView owns.
Should I subclass NSOpenGLView and add a pair of NSScrollers
Yes, since scrolling a OpenGL view doesn't make sense. You want to adjust the viewing volume (i.e. the parameters defining the projection matrix), rather than moving your viewport around. And that only works if you have manual control over the scroll bars.

UIScrollView always snaps back

I put a bunch of objects into a UIScrollView and I no have a problem: When I try to "scroll" to some off-screen objects, they appear so long as I am holding my finger down after dragging it, but when I let you, the UIScrollView snaps back to the original position.
Is there a way to prevent this? No off-screen gray area is appaering when this happens, BTW.
Thanks.
You have to set the scroll view's contentSize to include your objects, so it knows how large the scrollable area is — how far to scroll freely before it hits the edge and bounces back.
Try adding a Content Size Fitter component to the Scroll View's Content object and set its scroll direction (Horizontal Fit or Vertical Fit) to Preferred Size.

How does UIScrollView like scrolling work?

in my opinion the iPhone has a big advantage to other smartphones because of its intuitive, smooth and good feeling scrolling components in UIKit. I want to implement a simple game with UIKit which uses this kind of scrolling, but i can't use UIScrollView because it isn't customizable enough.
I tried to implement this scrolling myself and tried two different approaches:
I used a UIPanGestureRecognizer und moved the bounds of my custom control according to the translation the recognizer delivers me. In order to get this smooth scrolling after lifting my finger during the movement I start an animation. I use the velocity the recognizer gives me and a fixed time in order to calculate how far it should scroll after I lifted my finger. I tryed a linear movement and a ease-out movement, but both looks strange. (more later on that)
I use OnTouchMoved and OnTouchEnded to implement the scrolling. In OnTouchMove I move the bounds according to the movment of the finger. While the finger moves I calculate the difference in location and time of the current and last touch in order to calculate a velocity myself. When the finger lifts I start an animation in OnTouchEnded like in 1. but I use my self-calculated velocity instead.
Both approaches are not giving me the results I want. After lifting my finger, the scrolling is not smoothly continued. There seems to be a (sharp) bend in the celocity curve.
Has anyone an idea how apple does this smooth scrolling? My current guess is that my interpolation with two really close points is to inaccurate and doesn't take the current acceleration into account.
Thx for your thoughts!
Kie
Why don't you add a UIScrollView as handle on top of your view, without visible content. Then you can use the UIScrollViewDelegate methods to update your real view on certain actions. For example: if you capture the scrolling of the UIScrollView using scrollViewDidScroll: , you can update your visible view with the offset of the scrollview. You can use the scrollViewWillEndDragging: to start synchronizing the main view with the scrollview, and scrollViewDidEndDecelerating to stop synchronizing.
I use the same approach to scroll the background of my Animix app. It has an invisible scrollview at the bottom, to give the user the feeling he can drag the grass to the left and right to move the background.

Resources