registerForDraggedTypes with NSStatusBarButton? - macos

I'm trying to implement file drag and drop with an NSStatusBarItem.
All I really have is statusBarItem.button!.window?.registerForDraggedTypes([NSFilenamesPboardType]), but I don't know how or where to actually override methods like draggingEntered and performDragOperation.
I know it can be done with a custom view, but I'd like to stay away from deprecated methods if possible.

NSButton inherits from NSView. Therefore you can overlay a custom view which implements drag and drop functionality and add it as a subview to the NSButton. This approach avoids deprecated methods.

Related

Does Interface Builder's new IBDesignable attribute work with NSButton and other controls in Cocoa?

I have managed to get the IBDesignable/IBInspectable attributes working with direct subclasses of NSView but not with a direct subclass of NSButton. This is causing me to question if in fact the Cocoa implementation is somehow limited to NSView only.
Almost every example on the web (and Apple WWDC 2014 Xcode video) use NSView and then drag a custom view component from the library onto the canvas (and then change its class).
Is it possible to use IBDesignable with subclasses of NSControl and NSButton etc...? I have seen many examples on the web using UIButton.
If it is possible, then what are you supposed to drag from the library onto the canvas? It doesn't make sense for it to be a "custom view". On the other hand, there is no "custom control" available.
To be clear, I can get the IBInspectable attribute to show up at design time; but any changes don't seem to live render at design time.
The workaround is to wrap any custom NSButton I want to create within an NSView (via composition) but this seems like a bit of a hack...
I started playing around with a custom NSButton and NSButtonCell.
Dragging a button from the library onto the canvas and changing its class and the cell class doesn't live render. I think this is because Interface Builder still does a lot of custom things to setup NSButtonCell.
What works fine for me is dragging a custom view from the library onto the canvas and set its class. For this to work you need to setup the cell inside NSButtons -initWithCoder:.
Also I found a sample from Apple with a layer-backed custom Checkbox.
You need to drag an NSButton onto the view, then set the Custom Class to your specific NSButton descendant. Not sure why it doesn't work when you start with an NSView.
What can give you a hint is that the NSButton specific attributes aren't in the "Attributes Inspector". Hence there must be some setup at the time you drag the control onto the view.

Cocoa Programming: Adding a Rectangle to a Custom View (NSView)

Is there a simple way to add a simple rectangle to a Custom View without using a custom NSView subclass for it? Something along the lines of:
Assign an IBOutlet (let's call it colorWheelView) of NSView type to the CustomView
In my NSViewController's initWithNibName use it to change draw the rectangle:
// pseudocode
self.colorWheelView.addRectangle(myRectangle);
self.redraw()
The only way I've seen it done (on this site, and in my book Cocoa Programming for Mac OSX, pp. 241) is by making a custom class for the Custom View and modifying its drawRect method... Is this really the only way to accomplish this?
Edit: not sure why formatting is not being rendered correctly. I'm trying to fix it.
It really isn't all that hard to roll your own..
Just add an NSArray property to your NSView subclass, then in your drawRect method draw them either manually or using one of the NSRectFillList* methods provided by AppKit already.
(Beware: those take a plain C array, not an NSArray).
You wouldn't want to manually trigger the redraw from outside the view as in your sample code, though. To keep things consistent your addRectangle would trigger a redraw of the view itself e.g. by calling setNeedsDisplay:.

Dragging from NSBrowser and use bindings?

I've implemented a browser that shares NSTreeController with NSOutlineView so I can easily switch between them and keep the states in sync. Implementing drag support for NSOutlineView is simple, but it appears that NSBrowser cannot support dragging while using bindings. Has anyone been able to support dragging from NSBrowser while also using bindings?
I solved this by creating custom subclasses of NSBrowser, NSMatrix, and NSBrowserCell. I had to force NSBrowser to use NSRadioModeMatrix mode (single cell) by setting this mode in NSBrowser subclass -mouseDown method because it was constantly being reset.
In the NSBrowserCell subclass, I implemented trackMouse:inRect:ofView:untilMouseUp: by simply having superclass do it's thing, but returned NO so tracking would occur, which allowed mouseDragged: to be called in my NSMatrix subclass. In mouseDragged: I then did all the stuff to get the mouse location, construct a mouse image, and used [self dragImage:at:offset:pasteboard:source:slideBack:].
I'm not sure if this is the best approach, but it worked. It only works when there is a single selection allowed in NSBrowser.

Replace subview of NSSplitview with custom view

I still have a lot to learn with cocoa so I may have missed something obvious here. I have a custom view I would like to display in an nssplitview which replaces the current subview there.
I have a MessageView.xib file, and a MessageView .h/.m which subclasses NSView. I created a custom view instance for my main window (the one which contains the nssplitview) through Xcode 4's built in gui builder. I created an outlet to this instance of MessageView in my window's controller.
In my controller for the window when I want to swap out the subview for the splitview it runs this
[splitView replaceSubview:[[splitView subviews] objectAtIndex:1] with:viewMessage];
viewMessage is the outlet to the MessageView.
When this code is run the display of that subview changes to be blank. I'm not sure if there is something wrong with my custom view or there is some size issue. Is there something I need to do to fit the view into the split screen view or is my custom view just not displaying correctly? I have had a difficult time finding a tutorial on creating custom subviews with Xcode 4 so I'm not sure if something could be wrong with that. The custom view just has a label and a textfield in it.
Generally, you shouldn't need to replace NSSplitView's subviews with your own. Rather, you add your own custom view(s) as child views of the default subviews on each side of the divider. You can do this in code with addSubview:, but it's probably easier to just use Interface Builder in Xcode. Drag a "Custom View" into the splitview, then in the Identity Inspector, under Custom class, change the class to the name of your custom NSView subclass:
I think (off the top of my head, not tested), if you really do need to replace the default NSSplitView subviews with your own class, you can probably do it in Interface Builder using this same method, but selecting the default subview itself and changing its class in the inspector. This doesn't work for all AppKit classes, but it may work for NSSplitView.

buttons in interface buider

has anyone an idea if it is possible to create ellipse or polygon buttons in IB?
Directly, not without a library.
You can, however, create an NSView subclass which performs your shape drawing for you. You will need to implement the mouse events to perform clicks correctly. Drop an NSView on your window, set its class in the inspector to your custom-drawn NSView subclass, and you're set. Check out this tutorial.
You could also create a custom control, derived from NSControl. Check out this documentation.

Resources