NSTableCellView Drag Handle - objective-c

I've created an NSTableView that uses custom views for each row. In our design the user single clicks on a row in order to perform an action, which causes the table to be hidden (think a browser bookmarks menu implemented using a table view). I want the user to be able to enable an editing mode, which causes cells to display a drag handle (iOS style) that they can then use to reorder the rows. I've got the edit mode working and have implemented the necessary data source methods to enable drag and drop. The issue I'm struggling with is to only allow the user to drag using the drag handles, instead of being able drag the entire row. Is there a way to customize the hit testing so I can only have a drag session start when the mouse is over my drag handles?
Here's is an example of the interface in editing mode:

For future reference, I found the following function that I can override in the NSTableView in order to determine if a drag session should begin:
- (BOOL)canDragRowsWithIndexes:(NSIndexSet *)rowIndexes atPoint:(NSPoint)mouseDownPoint;
This allows me to check if the mouse down point is over the drag handle.

Related

Adding a toolbar button to Finder.app programmatically (macOS)

I am looking for a way to add several toolbar buttons to Finder, which, when clicked, perform certain actions.
My research shows that injecting code into Finder process is impossible on latest versions of macOS due to SIP, yet this would be the most seamless way for the user.
There is a possibility to add a toolbar item by creating a Finder Sync extension. However there are 2 problems:
There can be only one toolbar button per extension (I need several buttons)
The toolbar button will have a dropdown arrow (see an image below). I do not need to show a menu, however, and therefore this arrow makes the button misleading. It must be a simple plain button that matches the current system theme and performs an action upon click.
So this is what I don't need (because of the drop down arrow):
Update:
One of the ways to add a button, is drag and drop an .app bundle, holding Command key.
This approach has the following problems:
This button wouldn't match the other toolbar buttons look&feel, as the icon for such button is taken from the .app bundle (so it wouldn't switch based on macOS light/dark theme, for example)
It is impossible to add several toolbar buttons like that (as there needs to be one .app per 1 button). However, I need multiple buttons.
I am wondering if FinderSync allows creating "normal" (non menu) buttons
Is there a way to add a regular button to Finder's toolbar?
Please check out my Finder buttons:
https://github.com/lexrus/LTFinderButtons
Basically, I made every task a button app.
I'm trying Finder Sync Extension to do the same thing. All issues you found are true. Furthermore, there's problem #3:
You can not submit an app with Finder Sync Extension to the App Store.

Dynamically create views containing buttons - what about constraints?

I want a menu (hidden on the left side of my app) with a variable amount of buttons (depending on the user). I took the app over from another developer and he manually added every view and every button and it is a pain to maintain if you want to add another button in between or change something. So I want to redo it automatically.
But how can I achieve that? Let's say i have on the left x views, each containing an image, a button and a separator (to the button below). So I basically only create one single prototype view, button combo and reuse it for all other buttons. But how do I arrange them so the constraints are correctly set?
I would go with a table-view. Setup a cell with an image and a button, separators come for free in a table-view. Make sure the cell has a delegate for the button call-back or a closure to handle the button tap.
Add a controller/manager to control the number of views based on the user.

Set tab order in Mac app window

I'm creating a login form that's loaded from a nib. I have several NSTextFields, but when the app is launched, the one that gains focus immediately is the last one I added to the form. How do I set up the tab order and change or remove the initial focus?
In the Interface Builder: Right click on the NSTextField, link the nextKeyView with the object you want to be the next one that should be activated by pressing the "tab" button.
There's also an option called "Refuse First Responder". This option avoids the blue frame.

How to get the Spotlight-like text input effect in menu bar?

I want to have an icon in the menubar in my Mac app - and the icon should spawn a menu upon clicking. While having more entries in the menu, I would like to have a top row as a universal text entry field - like it is in Spotlight:
http://dl.dropbox.com/u/3943878/_mine/Screen%20shot%202011-07-16%20at%2012.29.18.png
Is it possible to add such a field to NSMenu? Or should I do it as a panel-type window?
If you're using xcode 4 , make a custom view in interface builder and add a textfield or anything you want to it. In IB also drag and drop a "Menu" from the objects library with as many items as you want in it. Then simply ctrl+click the menu item you want to make into the text field (In your case it would be the top one) and drag to the custom view and select "view". Now when you open the menu, instead of showing a menu item in that space, it shows whatever was in your custom view.
EDIT: As for your comment here's what you should do. Make your menu an outlet by opening the assistant editor view and ctrl+click from your menu to the header file that you want to use. now, simply make a method that will run whenever the menu will open, conveniently apple already made this, it's called menuWillOpen.
- (void)menuWillOpen: nameOfYourMenu{
[self performSelector:#selector(methodExecutedWhenMenuIsClicked) withObject:nil afterDelay:0.0 inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
the delay at 0 will make it happen immediately, it must be done in the common modes run loop so that the menu will be updated even while it's open. Now just make the methodExecutedWhenMenuIsClicked and set it so the text field responds.
- (void)methodExecutedWhenMenuIsClicked{
[[yourTextfiled window] makeFirstResponder:yourTextField];
You can put any view in a menu using -[NSMenuItem setView:]. See the long comment in NSMenuItem.h and the section Views in Menus in Application Menu and Pop-up List Programming Topics.
You're probably going to struggle quite a bit. I just tried doing the same thing, and reading the Views in Menus in Application Menu and Pop-up List Programming Topics document referenced by Ahruman, I found this:
A view in a menu item can receive all mouse events as normal, but keyboard events are not supported. During “non-sticky” menu tracking (that is, manipulating menus with the mouse button held down), a view in a menu item receives mouseDragged: events.
I think we're SOL. Apparently Spotlight pops up a borderless window instead.

How can I keep an NSPopUpButton open after the user selects a menu item?

I have an NSPopUpButton providing the NSMenu for a status item with a custom view. The popup button displays a list of links. When the user selects a link from the list, the link is displayed in the user's browser (in the background).
Naturally, the menu closes every time the user selects a link.
I would like to change this: I want the menu to stay open while the user clicks on various links, all of which can be opened in the background. The menu can then go away when the user clicks elsewhere.
How can this be accomplished? Should I subclass NSMenuItem and intercept the mouse clicks somehow? Overlay a transparent NSView on the popped-up menu and, again, intercept the clicks somehow? I make these suggestions blithely, but I would have trouble implementing either of these...pointers to the right methods for override would be appreciated.
Instead of using a menu, one might use a collapsible box.I have seen that in many apps ( also provided by Apple) , so I guess this is the recommended style guide for multiple selections.
The collapsible box expands when you click the disclosure button, and it gives free all items desired - like a tableview with checkboxes.
Views below this box must move down in this case, not to interfere with the box.
Clicking again on the disclosure button will shrink the box back to its origin. The effect is similar to closing a menu.
Usually you should not bend a control too far past it's original intent. Users expect pop up buttons to close after making a selection. I don't think you should, or can, force NSPopUpButtonCell to behave in this way. If you do, you'll be subclassing and modifying the control so heavily that it might change/break with a future version of Mac OS X. You'd also have to worry about the usability problem of users thinking the menu will close after making a selection.
You might consider writing you're own subclass of NSView to work like the menu button you're describing. After the user clicks on the button. You'll want to create a new NSWindow, with no border by using NSBorderlessWindowMask as the style mask. The content view of that window should be another custom view of yours that you implement the menu selection in.