views:

253

answers:

2

I have already created a status item for the menu bar but I would like to add a checkbox to make it able to be toggled on and off.

So when the check box is checked the status item is displayed and when the checkbox is not checked it is not displayed.

What code would i need to do this?

+1  A: 

Get an outlet to your button you want to toggle and then create an action method that your checkbox points to that toggles the hidden property of the original button based on the check box status.

crackity_jones
+5  A: 

First in your controller class create an instance variable to hold the reference to this item:

NSStatusItem *item;

Then create a method to create this status item, when the box is checked:

- (BOOL)createStatusItem
{
NSStatusBar *bar = [NSStatusBar systemStatusBar];

//Replace NSVariableStatusItemLength with NSSquareStatusItemLength if you
//want the item to be square
item = [bar statusItemWithLength:NSVariableStatusItemLength];

if(!item)
  return NO;

//As noted in the docs, the item must be retained as the receiver does not 
//retain the item, so otherwise will be deallocated
[item retain];

//Set the properties of the item
[item setTitle:@"MenuItem"];
[item setHighlightMode:YES];

//If you want a menu to be shown when the user clicks on the item
[item setMenu:menu]; //Assuming 'menu' is a pointer to an NSMenu instance

return YES;
}

Then create a method to remove the item when it is unchecked:

- (void)removeStatusItem
{
NSStatusBar *bar = [NSStatusBar systemStatusBar];
[bar removeStatusItem:item];
[item release];
}

Now tie it all together by creating an action that is called when the checkbox is toggled:

- (IBAction)toggleStatusItem:(id)sender
{
BOOL checked = [sender state];

if(checked) {
  BOOL createItem = [self createStatusItem];
  if(!createItem) {
    //Throw an error
    [sender setState:NO];
  }
}
else
  [self removeStatusItem];
}

Then create the checkbox in IB and set the action to your toggleStatusItem: method; make sure that the checkbox is left unchecked.

Edit (In response to errors) As stated above, you need to declare the NSStatusItem in the interface of the class that you have placed the createStatusItem and removeStatusItem methods; the reason that this becomes an instance variable rather than one local to the createStatusItem method is that there is no way to retrieve a pointer to an item that has already been added to the status bar in the Apple menu, and in order to remove the item once the checkbox is unchecked, you must store a pointer to this item. This will also solve your third error.

In response to your second error, I was merely demonstrating that if you want to add a menu to your status item when it is clicked, you must add the code for that yourself, retrieving a pointer to an NSMenu; I was showing how you could then add this menu item to the status bar item, if your pointer was called menu, hence my comment next to the line of code.

Perspx
Should I enter the main code (not the action) in the place where I have set up the status item?
Joshua
Yes, ideally you'd put the pointer to the status item in the controller class, and place the methods to remove/add it to the bar in this class also, along with the action.
Perspx
So i put all the code in the same controller class.
Joshua
Yes; creating a separate class to apply the changes would be unnecessary
Perspx
I've added the action to the controller but it's not seeing/noticing it in IB.
Joshua
You need to instantiate your controller class in IB; drag a blue "NSObject" object from the Library into the object window; then open up the inspector and in the Identity pane type your controller class name into the "Class" popup box. Then control+drag from your checkbox to the controller class, and select the toggleStatusItem: menu item from the popup menu to set its action.
Perspx
That's what i did thetoggleStatusItem: action wasn't in the list of actions.
Joshua
Check to see that you declared and implemented the method as - (IBAction)toggleStatusItem:(id)sender and that you declared it in the class interface.
Perspx
I know what I've done wrong, I'll see if it works now.
Joshua
I've got three errors, see the first post to see why.
Joshua
How would I declare the NSStatusItem? And would I delete the setMenu line if i didn't want a drop down menu?
Joshua
Simply with NSStatusItem *item; in your class's interface; and yes, I was just demonstrating that that's the line that you'd use if you did want a drop-down menu.
Perspx
I see, should I put NSStatusItem *item in the .m file or the .h file?
Joshua
In the .h file (where the class interface is defined)
Perspx
So I just paste in NSStatusItem *item into the .h file. Right?
Joshua
Yes, between the @interface and @end
Perspx
It works great now, thanks very much, just one last question, why can't the check box be checked as default, so it automatically display the status item?
Joshua
And also how would I make it display a image instead of text?
Joshua
Perhaps start a new question instead of simply commenting on this post; more people will be able to see your question and so you are more likely to get the specific answers that you want.
Perspx
Ok, although this question is based on your code, why doesn't the check box stay checked once you close the app, say you checked it when you opened it first when you open the app again it becomes unchecked. How could this be fixed?
Joshua
Why doesn't the check box stay checked once you close the app, say you checked it when you opened it first when you open the app again it becomes unchecked. How could this be fixed?
Joshua
That's a whole new venture entirely - you need to write the user's preference to the standard user defaults object in the NSUserDefaults class
Perspx
I've set up the NSUserDefaults class but if the check box is checked at opening it doesn't display the status item. How can I fix this?
Joshua
You need to determine whether the user wants the status item to be visible or not in your controller's awakeFromNib method, and add it to the menu bar if appropriate
Perspx
What code would I need to make the app determine whether the user wants the status item to be visible or not on launch?
Joshua
What code would I need to make the app determine whether the user wants the status item to be visible or not on launch?
Joshua
What code would I need to make the app determine whether the user wants the status item to be visible or not on launch?
Joshua
What code would I need to make the app determine whether the user wants the status item to be visible or not on launch?
Joshua