So I've set up an NSPopUpButton menu and populated it with the menu items and set all the key equivalents to what I want. The problem I'm having is that it automatically displays the key equivalent in the menu items next to the title of the item and I don't want it to. Is there any way to prevent it? I've searched the documentation and Google but can't seem to find anything about it.
the two ways that would come to mind would be to subclass NSMenuItemCell and do the following:
(untested, but seems like it should work)
- (NSRect)keyEquivalentRectForBounds:(NSRect)cellFrame
{
return NSZeroRect;
}
- (CGFloat)keyEquivalentWidth
{
return 0.0f;
}
or number 2 to remove the key equivalents and handle the events manually.
Related
I have a simple desktop app where a TextField should be focused when the window loads. I have this working, but it's a little annoying that, having loaded the users content into the TextField, the entire contents of the field become selected automatically. The user may want to start editing the content, but they will rarely/never want to replace it all at once (imagine a text editor doing this, to see what I mean).
I see there is an Action for selectAll: but what I want is the opposite Action of selectNone:
I tried passing nil to the selectText method, but that doesn't work:
textField.selectText(nil)
I found a number of answers on StackOverflow that mention a selectedTextRange, but this appears to be outdated, because Xcode 6.3 doesn't recognize this as a valid property on TextField.
Can anyone explain how I do this?
It's been a while since I've dealt with NSTextFields to this level (I work mostly in iOS these days).
After doing a little digging I found this on the net:
NSText* textEditor = [window fieldEditor:YES forObject:textField];
NSRange range = {start, length};
[textEditor setSelectedRange:range];
window is the window containing your field, textField.
This requires the field editor to be managing your field, what can be done simply by previously selecting the whole text of the field using the selectText:sender method.
Here is the final swift code that I got working based on what Duncan C posted:
if let window = NSApplication.sharedApplication().mainWindow {
let textEditor = window.fieldEditor(true, forObject: textField)!
let range = NSRange(0..<0)
textEditor.selectedRange = range
}
Any help would be great. I should add that I'm new to cocoa.
I currently check if I'm on Lion or Snow Leopard (by checking if the class NSTextFinder exists or not) and then set the find panel
[myTextView setUsesFindPanel:YES];
or the bar
[myTextView setUsesFindBar:YES];
Then in the delegate functions attached to Find and Find and Replace menu options, I simply call
-(IBAction)find:(id)sender {
[myTextView performFindPanelAction:sender];
}
-(IBAction)findAndReplace:(id)sender {
[myTextView performFindPanelAction:sender];
}
This works (at least on SL) i.e., displays the find and replace panel. The find next and the find previous do work from the panel itself via its buttons.
What I'd like to do is connect the menu options with find next/previous (via the usual Cmd-G and Shift-Cmd-G) without invoking the panel (as per the usual behaviour). I don't seem to be able to find a way to do that in my functions
-(IBAction)findNext:(id)sender {
}
-(IBAction)findPrevious:(id)sender {
}
An additional question: will the same code work for Lion's find bar?
Thanks in advance.
I have an NSPopUpButton with a long menu of items, some of which are quite wide - wider than the button's closed width. Some of the menu item titles are like so:
"Start of a really long name not that interesting (important info)"
When the menu is closed, this displays as:
"Start of a really long name not th..."
I'd like it to display as:
"Start of a really l... (important info)"
I can't figure out how NSPopUpButton is creating that ellipsis. Is there a selector being called on NSMenuItem? Does NSPopUpButton or NSMenu handle that somehow?
Which class do I need to subclass and which selector to I need to override or implement?
Many thanks.
This mechanism is called truncation. There is an option in Interface Builder called Line Breaks which is grouped in the Control group. The setting you're probably looking for is called Truncate Middle which will start picking letters from the middle of the menu item.
Note however that this won't solve your problem entirely as the (important info) part might not be the only one remaining after "…", but rather Name of my Me…tem (important info). Furthermore you might also end up with the important info partially truncated. But I figure you're fine as long as the important info is some number or a few letters.
Maybe adding an image to the menu item might suit your needs more (some sort of badge)? Maybe there is also an option for attributed strings to force letters to not be truncated… not sure however.
Fabian gave me the clue I needed. Thanks!
[[self cell] setLineBreakMode: NSLineBreakByTruncatingMiddle]
However, if there is a way to get finer-grained control, that would be even better. Is there a way to control the truncation more precisely?
I have a variable length NSStatusItem which I'd like to stay visible whenever possible, even if that means showing only some of the content, but when my item is wide enough to run into an application's menu bar, it is hidden entirely. Is there a way to tell when this happens so that I can shrink the view to fit available space?
I've experimented with a custom view, overriding all the viewWill* methods, the frame setters, and the display methods, and periodically checking whether the containing window has moved or become hidden. I can't find any way to tell when my item is too long.
This depends on whether your status item application can detect the number of menu items in the OS X menu bar. A quick search through apple documentation shows that there are no public APIs provided by Apple for the purpose of doing this. To my knowledge, there are no private ones available too.
So I would recommend instead that you make your status item small by default and expanded when clicked by the user.
Edit:
Actually look at the discussion here: a really clever way to detect if your status item is being hidden. So once you have detected that it is being hidden, you can shrink it so that it reappears.
Here's a complete working example based on the discussion that hollow7 referenced:
self.statusItem.title = #"Message that will be truncated as necessary.";
while (self.statusItem.title.length > 0) {
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenAboveWindow, (CGWindowID)self.statusItemWindow.windowNumber);
if (CFArrayGetCount(windowList) > 1) {
CFRelease(windowList);
self.statusItem.title = [self.statusItem.title substringToIndex:self.statusItem.title.length - 1];
} else {
CFRelease(windowList);
break;
}
}
A tricky part that remains is getting the NSStatusItem window. So far, I've found two methods for obtaining it.
1 - There's a private method called _window. You can utilize it like this:
self.statusItemWindow = [self.statusItem performSelector:#selector(_window)];
2 - This is a bit more complicated but I think this is more likely to pass Apple's static analysis for private method usage in the Mac App Store:
Set the target and action of the NSStatusItem to a method you control, like this:
self.statusItem.target = self;
self.statusItem.action = #selector(itemClicked:);
Then access the window in the invoked method:
- (void)itemClicked:(id)sender {
self.statusItemWindow = [[NSApp currentEvent] window];
}
I'm implementing a custom status bar menu, which has a custom view with NSSearchField. I'm updating number of menu items according to search results. The number of menu items is changed as user types in the NSSearchField. I've noticed, that if number of results stays the same, items titles are not updated (redrawn). How do I force them to redraw?
In the function, that rebuilds the menu I remove first all items and then create new items according to the search results.
Thanks,
Nava
I could achieve it by following approach: When the number of search results is the same, i don't recreate them, just change the title and call itemChanged:. When the count is different I recreate menu items. This works anyway. But I was advised anyway to get back from using menu for this purposes.
on the menu set menuChangedMessagesEnabled to YES when you want to update the menu:
[menu setMenuChangedMessagesEnabled:NO];
// change the menu
[menu setMenuChangedMessagesEnabled:YES];
The second invocation causes the menu to apply changes. The first one is so that you can batch a group of changes together.
That said, Apple guidelines discourages changing menus while they're open as users are not used to this and can be confusing. If it's feasible try to redesign your app so you can use something else, say a table or matrix, instead of a menu.