NSEvent from a NSButton - objective-c

I have a NSTableView and each row contains a button. I also have a menu associated with the table.
The issue is : I want to show the menu on click of button. If possible do not show on right click.
The action method is :
- (IBAction)showMenu:(NSButton *)button {
NSLog(#"show menu");
NSMenu *menu = [self.tableView menu];
NSEvent *event = [[NSEvent alloc] init];
[NSMenu popUpContextMenu:menu
withEvent:event
forView:button];
}
Here what to do with event? If I use nil then the menu is showed at bottom left corner, not next to the button.
Any guidance would be appreciated.

You could try using -[NSMenu popUpMenuPositioningItem:atLocation:inView:]. This method doesn't take an NSEvent argument. Instead, you give it a view and a location in the view's coordinate system, and the menu positions itself (or one of its items) over that location.
But I would suggest you don't use an NSButton at all. If you use an NSPopUpButton instead, it will take care of showing the menu at the correct location on a left-click.

Related

Show NSWindow on right click in NSTableView

I'd like to display an NSWindow when right clicking an item in an NSTableView, similarly to how the available outlets are shown in Interface Builder when you right click an object:
Unfortunately you can only use an NSMenu subclass as the menu property.
I also didn't find a delegate method of NSTableView that notifies about right clicks.
I was able to subclass NSTableView and implement rightMouseDown: and rightMouseUp: to be notified about those events, but if I set the menu property of the row cells to nil, they are not highlighted when right clicked, even though I call the super implementation):
- (void)rightMouseDown:(NSEvent *)theEvent {
[super rightMouseDown:theEvent];
NSPoint eventLocation = [theEvent locationInWindow];
eventLocation = [self convertPoint:eventLocation fromView:nil];
NSInteger rowIndex = [self rowAtPoint:eventLocation];
NSLog(#"Right clicked at row index %d", rowIndex);
}
I would like to have the highlight effect in the image below but display a window instead of the context menu:
First for the right click: explicitly select the row on right click (e.g. via this message). Then create your own NSWindow descendant, set an own NSView class as contentView and in the view you can draw the black background, rounded borders and what not. Show this window in your right click handler.
You can use an NSPopover, which works quite nicely. A popover creates a window for you, even if it is somewhat hidden. You'll get it from your controls if you send them the window message, and can register to listen for events, for instance.
The whole popover can be created in IB, and just have to implement the showRelativeToRect:ofView:preferredEdge: method in code.
To catch the right click event, you can use rightMouseDown:, which is originally defined in NSResponder, but is overridden in NSView to simply catch the event and show menu and it doesn't pass the event upwards in the responder chain (or the inheritance chain, for that matter). Hence, you simply implement that method to call showRelativeToRect:ofView:preferredEdge:.
You will typically need to have the contents in an NSViewController and its own accompanying nib file.
The NSPopover's contentViewController property can be set in IB, too.
All in all, not much code needed.
This tutorial is useful.

Adding BarButtonItems to backButton in view controller

i have a view controller, which is standalone and has two left UIBarButtonItem, however when i push it, i want to have these two buttons + the back button
i tried
- (void)viewDidLoad
{
[super viewDidLoad];
// back
if (self.navigationController.navigationItem.backBarButtonItem) {
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:self.navigationController.navigationItem.backBarButtonItem, self.barButtonFilter, self.barButtonFilterContacts, nil];
} else {
self.navigationItem.leftBarButtonItems = [NSArray arrayWithObjects:self.barButtonFilter, self.barButtonFilterContacts, nil];
}
}
if there is a back button, than add, else replace
but i didnt work
I am not able to get your problem but according to your caption you want to replace you back button of UINavigationController with a bar button item, in that case you simply need to have a custom button in place of back Button:
UIBarButtonItem *backButton= [[UIBarButtonItem alloc] initWithTitle:#"yourTitle" style:UIBarButtonItemStylePlain target:self action:#selector(someFunction:)];
self.navigationItem.rightBarButtonItem = backButton;
[backButtonrelease];
If this is not your problem please elaborate.
So the issue here is that a UINavigationBar can only have one leftButtonItem and one rightButtonItem. But What you can do is in the center of the UINavigationBar you can have a UIView. You can use this to place the buttons on.
Someone has the code here: adding-buttons-to-the-titleview-of-navigationbar-without-having-to-repeat-code
From Apple's iOS Human Interface Guidelines:
Use a toolbar instead of a navigation bar if you need to offer a
larger set of controls, or you do not need to enable navigation.
Avoid crowding a navigation bar with additional controls, even if
there appears to be enough space. The navigation bar should contain no
more than a view’s current title, the back button, and one control
that manages the view’s contents. If, instead, you use a segmented
control in the navigation bar, the bar should not display a title and
it should not contain any controls other than the segmented control.
http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/mobilehig/UIElementGuidelines/UIElementGuidelines.html

How I add a mouse right-down menu to the NSCollectionViewItem

I have a question.How I add a mouse right-down menu to the NSCollectionViewItem.
As an attempt I alse use the Apple's demo app IconCollection.I tryed drag a NSMenu to the IconViewPrototype.xib and connect it to the view's menu outlet in IB.but when build and run,click the mouse right click,nothing happened.I think the NSBox also a subclass for NSView,the mouse right-down menu should be support.
I ended up creating an NSView subclass to use as a View for the CollectionViewItem. In there I set a delegate (connected in IB), and used this to catch the right mouse click and open the menu:
-(void)rightMouseDown:(NSEvent *)theEvent {
NSMenu *menu = [self.delegate menuForCollectionItemView:self];
[menu popUpMenuPositioningItem:[[menu itemArray] objectAtIndex:0]
atLocation:NSZeroPoint
inView:self];
}
This still needs some code to position the menu where the user clicked, but it's a start.
If anyone has a cleaner method I'd love to hear it.

How do I add a navigation bar's Done button to a popover's passthroughViews?

I'm working in an iPad app that has a split view with a navigation controller in the detail view. The deepest view that can be in the navigation stack is an edit view where the user can edit data. I put an edit button as the rightBarButtonItem and when editing starts, change it to a done button.
When editing commences and the user touches on a particular field, I present a popoverview with a list of possible choices filtered by what they are typing - a form of autofill based on all the values of that field in all other objects.
This works fine, except if you try touching on the done button. The popover eats this touch and dismisses itself. So the user has to touch done again.
I tried using the uipopovercontroller's passthroughViews property, but UIBarButtonItem is not a view and there is no documented way to get the view for the done button or even the navigation bar. I can access the variable in gdb, but it isn't accessible via KVC.
Any ideas on how I can prevent the need to tap done twice?
I've thought about a gesture recognizer on the window, but that seems messy and I'd have to handle rotation.
In case anyone gets here from google, copypaste from other question:
The only solution I found for now is to create UIBarButtonItem with custom UIButton using
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
//code for styling button
UIBarButtonItem *b = [[[UIBarButtonItem alloc]
initWithCustomView:button]
autorelease]
and then
popoverController.passthroughViews = [NSArray arrayWithObject:b.customView];
But be prepared - you cannot create UIButton that looks like UIBarButtoItem. I ended up with creating image that reassembled UIBarButtonItem.

NSPopUpButton in a TrackingArea -> mouse exited when selecting an item from the menu

I have an NSPopUpButton inside a trackingArea. Now when I open the PopUp and select an item, the mouseExited: method gets called. Even if my mouse is still inside the trackingArea. I assume that that is because the NSMenu is a view itself and when I click the mouse it is not in the view with the tracking rect anymore.
How can i workaround this problem? Is there a way to set a tracking area on top of all views?
The tracking area I use:
NSUInteger options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow;
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:rect options:options owner:self userInfo:nil];
Try NSTrackingActiveInActiveApp instead of NSTrackingActiveInKeyWindow. I'm not sure about this offhand, but it's possible that the window resigns key status (but not main, which would be why its appearance doesn't change) when the menu begins tracking, so that the user can navigate the menu with the keyboard. (You could check this by being the window's delegate and responding to a couple of delegate messages.)
Of course, this does mean you'll have to check whether the window is main before handling the user's mouse movements.