cocoa application changing mouse cursor? - objective-c

I have a cocoa application that has a view which is clickable. I cannot figure out how to change the cursor when the user mouses over it. I want to do this so that the user knows that they can click on it. I know this should be very simple, but I have not been able to find anything via google or stackoverflow. Anyone have any ideas?

So, not this?
Cocoa: change cursor when it's over an NSButton
[yourButton addCursorRect:[yourButton bounds] cursor:[theCursorYouWant]];
(Quote from Mark)

This is a relatively simple thing to do using NSView's tracking areas methods in conjunction with the NSCursor class to change the cursor. In general, the way you do this is set up a tracking area for your view, and when you get mouseEntered and mouseExited updates from the tracking area, you can update the cursor.
Check out the NSView Class Reference and the NSCursor Class Reference for more information.

Related

Snapping an NSWindows in place while the user is moving it

What would be the best way to snap an NSWindow to some location while the user is moving it?
I have tried using windowDidMove, for mouse down events, but this function is called for every single movement. I haven't been able to find anything equivalent to the old kEventWindowBoundsChanging with kWindowBoundsChangeUserDrag, which was exactly what was needed to do this. It needs to be available in 10.7 on up.
Any leads?
Generally the easiest way to do this is subclass NSWindow and implement -setFrame:, where you modify the NSRect argument and then pass it to super.

Setting the text on UIButtonLabel on a PLUICameraViewController

I'm trying to set the text of the "Retake" and "Use" buttons on the PLUICameraViewController. I've programmatically navigated through the view hierarchy and found a few UIButtonLabel objects. Logging the text of these shows what I expect: "Retake", "Cancel" etc. However setting the text doesn't work. The buttons just keep their original text. Here's what I've tried:
if (q is a subclass of UIButtonLabel)
if ([q respondsToSelector:#selector(setText:)])
[q performSelector:#selector(setText:) withObject:#"zzz"];
The code runs w/o crashing. Also respondsToSelector is returning YES. How can I make the text on the buttons update?
By the way I'm aware of other approaches involving custom buttons, my own views etc. I'm really curious from an Objective-C/runtime/iOS perspective why the above code doesn't work.
Also note I'm doing this in
navigationController:willShowViewController:viewController:animated:
In this case, I don't think it's an issue of Private APIs, per se. This is just the way UIButton works.
Yes, the title of the button is a UILabel, and in practice, it is probably/currently an instance of the private class UIButtonLabel. But, the way Apple intends for you to change the title text is to use the methods in UIButton itself:
[self.button setTitle: #"newTitle" forState: UIControlStateNormal];
[self.button setTitle: #"newTitle" forState: UIControlStateSelected];
instead of trying to drill down into the button's subview heirarchy, find a button label, and call setText:.
Here's the relevant API documentation
As to why it doesn't work, I suppose that's because Apple wants it that way.
For one, changing a button's title is expected to be a normal use case. So, for convenience, they probably wanted to give you an easy method to call, directly in the UIButton interface. If they forced you do drill down into the view hierarchy, not only would you have to write more code, but it makes it a little harder for Apple to change the underlying implementation of a button. They may want to preserve the ability to change it later, and for that, it's better for them to keep some sort of wrapper APIs at the UIButton level.
Also, if you directly change the text on the button label, you are circumventing their design, where the label text depends on the button state (e.g. normal, highlighted, selected, etc.) Even though most people probably use the same button text for all states, the design allows for state-dependent text, and therefore, hiding the underlying UIButtonLabel helps enforce this design.
That's my guess as to their motivation.
So, to enforce this, it's entirely possible that in their implementation of UIButtonLabel setText:, they decline to update the text after the button has been initialized. After that, you have to use the setTitle:forState: method.

Changing focus from NSTextField to NSOpenGLView?

I am developing an interface for an OpenGL Simulation on the Mac using Interface Builder. All OpenGL stuff is being written in C++ (which I know fairly well). Unfortunately I have no idea about Objective-C.
Basically, I have a few NSTextField displaying info on an object selected on the Screen. Using these textfields the user is the able to manipulate the object on screen and then there is a Save Button and a Restore Button (which either save the new values or restore the original ones)
I have this all working. My problem is when I enter data into an NSTextField the "focus" of the windows seems to remain on the NSTextField (blue border remains around it).
I use the keyboard to interact with items within the NSOpenGLView, I need to pass the focus back to the NSOpenGLView when I hit either the Save or Restore buttons.
Sorry if this is a very straightforward question
Thanks
David
Have you tried using NSWindow makeFirstResponder method to make your NSOpenGLView the first responder?
Just managed to get it working.
I had to add the line:
[[NSApp keyWindow] makeFirstResponder: MyOpenGLView];
to the end of the function being called when I click on either of my buttons.
(Thanks Julio for pointing me in the right direction)

How to stop mouse drag events from moving entire window? [cocoa]

I think this should be a very easy one, but I cant find the answer on the docs.
I want to stop mouse dragging events which are in (or start in) my custom nsview subclass from causing the window to be dragged around the screen. How can I tell the window to stay still so i can interact with the view instead of dragging the whole window around? thanks.
In addition to the matter of whether you handle mouseDragged, you may need to override mouseDownCanMoveWindow to return NO, or override isOpaque to return YES.
You need to implement mouseDragged: in your view. As documented, NSView's implementation simply passes the message to the next responder, which means that it will end up hitting the window. (Why? See “The Responder Chain” in the Cocoa Event-Handling Guide.) Responding to the message yourself prevents that, as long as you don't call up to the superclass implementation.

Looking for info on custom drawing of interface components (Cocoa)

It seems like more and more OS X apps these days are doing all kinds of fancy drawing stuff for custom controls. Apps like Twitterific, Things, EventBox, Versions just to name a few....
So basically I'm looking for any information on how to get started doing this kind of thing. Not sure if it is just done by subclassing controls and using custom drawing or if it is something entirely different.
Any help is greatly appreciated. THanks!
It depends entirely on what you want to do.
The "Show Raw Properties" button in Versions for instance is an NSButton subclass, because basically what we needed is standard button behavior with our own look.  One way to subclass a button is to simply implement your own -drawRect:(NSRect)rect method in the NSButton subclass, but we decided to stick with the way NSButton is implemented in Cocoa, meaning most drawing is done by the button's cell, so the implementation looks like this:
In the NSButton subclass:
+ (Class) cellClass
{
return [OurButtonCell class];
}
- (void)drawRect:(NSRect)rect
{
// first get the cell to draw inside our bounds
// then draw a focus ring if that's appropriate
}
In the NSButtonCell subclass (OurButtonCell):
- (void)drawInteriorWithFrame: (NSRect) rect inView: (NSView *) controlView
{
// a bunch of drawing code
}
The Timeline view in Versions is actually a WebView, the page that you see in it uses javascript to collapse headers you click on.
The rule of thumb I use for where to start out with a custom control is:
To customize the look of a standard Cocoa control:
subclass the appropriate control (like e.g. NSButton and NSButtonCell)
stick as close as makes sense to the way the default control is implemented (e.g. in a buttoncell, start from the existing attributedTitle instance method to draw the button title, unless you always want to draw with the same attributes regardless of what's set up in IB or if you need to draw with different attributes based on state, such as with the trial expiration button in Versions' main window)
Creating an entirely new UI element:
subclass NSView and implement pretty much all mouse and key event handling (within the view, no need to redo "hitTest:") and drawing code yourself.
To present something that's complex, of arbitrary height, but isn't a table:
See if you can do it in HTML, CSS and JS and present it in a WebView.  The web is great at laying out text, so if you can offload that responsibility to your WebView, that can be a huge savings in pain in the neck.
Recommended reading on learning how to draw stuff in your own custom view's drawing methods: Cocoa Drawing Guide
Customizing the look of for instance an NSTableView is an entirely other cup of tea, thanks to the complexity of a tableview, that can happen all over the place.  You'll be implementing your own custom cells for some things you want to do in a table, but will have to change the way rows are highlighted in a subclass of the actual NSTableView object itself.  See for instance the source code for iTableView on Matt Gemmell's site for a clear example of where to draw what.
Finally, I think Abizer's suggestion to go check out the code of BWToolkit is a great idea.  It might be a bit overwhelming at first, but if you can read and understand that code you'll have no trouble implementing your own custom views and controls.
Have a look at some excellent example code: BWToolkit