Selecting text programmatically in menu view - objective-c

I write an "Agent" Cocoa app where I have TextField in status icon's menu, it looks like this:
(source: ifotos.pl)
And in couple of places I select its contents programmatically (e.g. in -(BOOL)becomeFirstResponder of my NSTextField subclass)
And it doesn't work. It surely has something to do with the fact that it's in menu, not in window. But how do I fix that?

Because your view is in a menu, it's possible that the textfield isn't responding because the run loop is not in its default mode. Try calling selectText: like this:
[textField performSelector:#selector(selectText:) withObject:nil
afterDelay:0.0 inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];

Why don't you just use a window instead? Menus are implemented as windows under the hood: you can do the same thing, just position and style your window appropriately.
Edit: answer largely rewritten

Related

NSWindow levels and modal dialogs

I have an application that needs to display a window on top of anythings else. To achieve this I call [window setLevel:NSStatusWindowLevel] on my main window.
This works fine except that I can't use any modal dialogs or alerts from this window. The problem seems to be that [NSWindow beginSheet...] internally calls setLevel: on the target modal window with a value lower than NSStatusWindowLevel, so the modal dialog is displayed behind its parent window. The same happens when using an NSAlert from a window with higher window level, the alert is displayed behind.
The only [ugly] workaround I found is to inherit NSWindow, override setLevel: and prevent setting a lower level value on these modal windows but this only works when I have control over the window and doesn't work for NSAlerts.
Is there a more elegant solution for displaying modal dialogs from a NSWindow with high window level value that will also work with NSAlerts? Or I will be unable to use NSAlert with this approach?
one thing that comes to mind is to check if NSAlert uses a special NSWindow subclass you could make a category on it and hook the setLevel: method via swizzling (here is an example of extending an existing method via swizzling). there is nothing stopping you from doing this in a plain NSWindow subclass either.
I know its not the "elegant solution" you'd hoped for, but its the only one I know off the top of my head. I suppose it is slightly more elegant in that you don't have to insert your custom subclass everywhere throughout your program, but less elegant in that you are messing with the objective-c runtime using code that simply seems wrong.

NSTextField inside NSPopover is not key until mouse click

I've got an NSPopover that is shown from interaction with an NSStatusItem. I've blogged about the hacks I needed to do to make input even possible in this situation here: http://blog.brokenrobotllc.com/using-nspopover-with-nsstatusitem
I have an NSTextField inside the NSPopover's content view. When I open the NSPopover, the NSTextField appears as if it is key (the cursor blinks). But, when typing, nothing shows up. If I click the mouse in the field, my input starts showing up there.
I've tried things like invoking NSWindow's makeFirstResponder upon popoverDidShow:. There was no change in behavior from this. Anyone have any ideas here?
My guess is you need to make your app active; try calling
[NSApp activateIgnoringOtherApps:YES];
when you show your popover.
Edit: Of course, I could be wrong. This is all just off the top of my head.

Custom NSMenu item

how can i go about making a custom NSMenu for a menulet such as this?
Is this an NSMenu or is it a borderless window and if so how would i go about this?
Thanks!
It's an app running running on the OSX status bar.
See Status Bar Programming at Apple. Also, NSStatusBar and NSStatusItem
This SO post has some additional pointers:
How to create a Menubar application for Mac
More specifically it could be an NSPopover, an NSWindow, or even NSStatusItem.view's custom view. In the case of an NSWindow (often a utility form of NSPanel) (or the NSPopover) you would manually open the window when the status item is clicked, using the status item's -(void)setAction and -(void)setTarget. If you use a custom view for the status item, this would be done in -mouseDown:.
Check out this post - I found it useful.
Look at the documentation for NSStatusItem. I believe you can have it display a view instead of a standard NSMenu which is what it looks like they are doing in that image.

NSTextField inside NSMenu -- doesn't interact or look as expected

I'm attempting to create a log-in window inside an NSMenu (attached to the an NSStatusItem in the menu bar).
I have blank NSMenuItems in the menu. I then set the views of the menu items to NSTextFields.
It ends up looking like this:
The textfields also interact strangely. Clicking on them only gives them focus (so you can enter text) about 30% of the time.
So, I'm wondering:
-How do do I make these look better? How do I control the padding, etc?
-What's with the clicking behavior I described above? Typing only works 30% of the time.
-Are there any other apps that use such a statusbar item as a field? I'd like to take a look.
To answer your actual question instead of discussing the UI design...
Alternative:
Consider using the MAAttachedWindow project from Matt Gemmel:
Download the use an MAAttachedWindow with an NSStatusItem example.
Link:
http://mattgemmell.com/source/index.html
Quickly created example:
Used controls:
- NSTextField (Focus:None DrawsBackground:No TextColor:White)
- NSButton (Bezel:Recessed)
- NSLabel (TextColor:White)

Disable NSToolbar customisation via window's toolbar button?

I am looking to disable the Command + Click combination on a toolbar button (located top-right) in a Cocoa window. I would still like to let the user show and hide the toolbar, but I do not want them to be able to select a different display mode (e.g. small icons, no icons, etc).
Has anyone found a way to do this? Thanks in advance.
You don't need to subclass NSToolbar to do this. In your NSWindowController subclass, put the following in your awakeFromNib:
- (void) awakeFromNib
{
NSToolbar *tb = [[self window] toolbar];
[tb setAllowsUserCustomization:NO];
}
You also have the added benefit of avoiding private API use.
Have you tried using a custom NSToolbar subclass that overrides setDisplayMode: and setSizeMode: to do nothing? That won't remove the menu items of course, or the UI in the customization sheet (assuming you aren't disabling that as well with setAllowsUserCustomization:), but it might prevent them from doing anything.