Objective-C: How to create a Menu with custom UI? - objective-c

I'm trying to develop an application in Xcode 4.1. I would like to create an application located in the menu bar, like described in this tutorial:
http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/
But instead of showing a standard Menu when clicking, I would like to show a more graphical UI with some text fields, buttons, etc. like they do in Fantastical:
http://flexibits.com/fantastical
I hope someone can tell me, how I can do.

Here's the Status Bar Programming Topics guide.
Make an NSStatusItem. Set the item's view to a custom view that you create. This view will appear in the status bar and receive mouse clicks.
Make your custom view handle a mouse click by presenting a window with your custom UI.

It's not necessary to use a custom view. All you have to do is set the status item's target & action to your method which shows the window:
[self.statusItem setTarget:self];
[self.statusItem setAction:#selector(ShowOrHideWindow:)];

Related

View hierarchy used by the Pages Mac OS X app

I need to build a Mac OS X app which requires view hierarchy similar to the Pages app. I understand that their is a toolbar at the top. On the left is a scroll view that contains a custom view but I have problem figuring out the hierarchy on the right, specifically the scroll section used on the right which allows options to hide or show up dynamically depending on the other options.
This is called an inspector view. It is not apart of the public SDK; this is all private code.
If you want to see how it's made start a view debugging session in xcode and attach it to the pages process. What you will find:
Inspector View
Inspector Pane Group view and Inspector Segmented Control
Inspector Pane View and Inspector Pane Disclosure Views.
You can make this fairly quickly from existing UI views and controls.

Make an NSToolbar's fullScreenAccessoryView visible at launch

I am trying to make an application with a toolbar controller which view is shown, and for each view shown I want to include a second 'row' for the toolbar, and I found out that to do this you had to do [toolbar setFullScreenAccessoryView:view]. However, the view does not appear until the user toggles fullscreen mode and the accessory view remains after toggling the window back to windowed mode. I would like it to look like the following examples from Mail.app, Preview.app, Dictionary.app:
just place a custom view underneath the NSToolbarView .. so at the top of the window.
dont misuse the fullscreenAccessory view. it if meant for something else.
see How to create a toolbar with "Search" Finder style, rounded buttons working like radio
(it could be any other view too btw :D)

Displaying Tabview instead of Menu in Menubar App

I am new to OSX App development and finds things a little different from that of iOS. I am trying to create a sample Menubar App. I can display a menu using the command
[statusItem setMenu: startMenu];
But i dont know how can i display a TabView instead of menu. Can some body help me with this.
where statusMenu is an outlet of NSMenu and statusitem is an object of NSStatusItem
You cant. You have to display it in a window, which you can open on the click of the status item.
You can make the window borderless.
1.
You can either use this one here, which is a NSTableView in a window, which can fake the layout of a NSMenu:
JGMenuWindow
Though I would not recommend that, because if Mac OS X has some layout changes, this will stay the same.
2.
Or you can use a normal window, which you customise, like here:
Popup
You can set the custom view of a NSMenuItem, so you could just try adding your tableview to the NSMenuItem of choice.

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 would you make a Status Item show or Hide a window when clicked?

How would make a Status Item when the actually button is clicked in the Menu Bar not in a drop down menu show or hide a window?
Sorry if this is a bit vague.
NSStatusItem supports the target/action mechanism like many other controls. I haven't used this myself -- I've only ever used an NSStatusItem with a menu attached -- so I don't know when the message is sent (i.e. when the mouse button is clicked or when it's released). If it doesn't do what you want by default, you would need a custom view like Daniel suggests.
To achieve this with NSStatusItem you need to create a custom view and replace the default NSStatusItem view by calling its "setView:" method.
You'll implement code in your custom view to react to mouse clicks by e.g. putting up a window. (You can use a button, or other standard views if it works best for you).
I'll warn you this is a bit tricky to get right. Lots of little nuances e.g. with getting the look of your custom view to look right in the menu bar. But this is the general approach you need to take if you want to override the default menu-prompting status item view.