 |
 |
NSStatusBar and NSUIElement..input needed.
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
Okay, I "wrote" an application that showed a window when you selected a menu item. After compiling, I opened the package and edited the Info.plist file. I added:
<key>NSUIElement</key>
<string>1</string>
Well, surprise..no Dock icon and no menu bar. If my app had relied on the user being able to select that menu item the application would be pretty pointless now and the user would have to quit the application from the terminal.
I had come up with a pretty twisted way to do what this class does at first. I wasn't exactly thinking in terms of re-use at that point. Well, I decided I should probably add something like this to my apps and I wanted something easy to re-use...
Code:
// FallbackMenuController.h
// Created by Ryan Stevens on Fri Apr 20 2001.
#import <Cocoa/Cocoa.h>
typedef enum _DockIconState {
DockIconVisible = 0,
DockIconInvisible = 1
} DockIconState;
@interface FallbackMenuController : NSObject {
NSString *path;
NSMenu *fallbackMenu;
NSStatusItem *fallbackMenuStatusItem;
BOOL isIconVisible;
}
// show/hide methods.
- (void)showFallbackMenu:(NSString *)label;
- (void)removeFallbackMenu;
// creates a menu with an About and Quit item.
- (void)createDefaultMenuWithIdentifier:(NSString *)appname;
// uses the specified menu instead of the default.
- (void)setFallbackMenu:(NSMenu *)menu;
// tells us if the icon is currently showing.
- (BOOL)showingIconInDock;
// saves whichever state.
- (void)saveIconState:(DockIconState)state;
@end
// FallbackMenuController.m
// Created by Ryan Stevens on Fri Apr 20 2001.
#import "FallbackMenuController.h"
@implementation FallbackMenuController
- (void)showFallbackMenu:(NSString *)label
{
NSStatusBar *globalMenu = [NSStatusBar systemStatusBar];
if (fallbackMenu == nil) [self createDefaultMenuWithIdentifier:label];
fallbackMenuStatusItem = [[globalMenu statusItemWithLength:NSVariableStatusItemLength] retain];
[fallbackMenuStatusItem setTitle:label];
[fallbackMenuStatusItem setMenu:fallbackMenu];
}
- (void)removeFallbackMenu
{
[fallbackMenuStatusItem release];
[fallbackMenu release];
fallbackMenuStatusItem = nil;
fallbackMenu = nil;
}
- (void)dealloc
{
[self removeFallbackMenu];
[super dealloc];
}
// Could add the standard help item.
// This could be done using a .nib but this is ok too.
- (void)createDefaultMenuWithIdentifier:(NSString *)appname
{
NSMenuItem *newItem;
newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:@"." action:NULL keyEquivalent:@""];
fallbackMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] initWithTitle:@"."];
[newItem setSubmenu:fallbackMenu];
[newItem release];
// About item.
newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[@"About " stringByAppendingString:appname] action:NULL keyEquivalent:@""];
[newItem setTarget:[NSApplication sharedApplication]];
[newItem setAction:@selector(orderFrontStandardAboutPanel:)];
[fallbackMenu addItem:newItem];
[newItem release];
// a separator.
newItem = [NSMenuItem separatorItem];
[fallbackMenu addItem:newItem];
// Quit item.
newItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[@"Quit " stringByAppendingString:appname] action:NULL keyEquivalent:@""];
[newItem setTarget:[NSApplication sharedApplication]];
[newItem setAction:@selector(terminate:)];
[fallbackMenu addItem:newItem];
[newItem release];
}
- (void)setFallbackMenu:(NSMenu *)menu
{
// should be retaining? ahh..oh well..
fallbackMenu = menu;
}
// There's probably a better way to do this.
- (BOOL)showingIconInDock
{
static int called = 0;
NSDictionary *info_dict;
if (called == 0) {
path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/Contents/Info.plist"];
info_dict = [NSDictionary dictionaryWithContentsOfFile:path];
if ([[info_dict objectForKey:@"NSUIElement"] isEqualToString:@"1"])
isIconVisible = NO;
else
isIconVisible = YES;
called = 1;
}
return isIconVisible;
}
- (void)saveIconState:(DockIconState)state
{
NSMutableDictionary *info_dict = [NSMutableDictionary dictionaryWithContentsOfFile:path];
// This should be ok, I think.
if (state == 0)
[info_dict setObject:@"0" forKey:@"NSUIElement"];
else
[info_dict setObject:@"1" forKey:@"NSUIElement"];
[info_dict writeToFile:path atomically:YES];
}
@end
Ideas, comments or corrections? Part of the idea was to get some input on ways to improve it. I'm still learning so be gentle!
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
I figured someone would want to jump on my mistakes.
Well, back to the top with this topic. 
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
Since nobody else wanted to jump in I'll throw up some corrections of my own..
It should check for NSBGOnly too.
There needs to be some form of addition to see what the state of the icon will be on next launch.
So, - (BOOL)willShowIconInDock could be added to see what the next run will do.
Right?
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
In - (void)showFallbackMenu  NSString *)label
it needs to have:
if (label == nil) label = [[NSProcessInfo processInfo] processName];
As a just-in-case. At least then we would have some form of indentifier for the menu no matter what.
Anything else I've missed?
|
|
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
correction:
Code:
- (void)setFallbackMenu NSMenu *)menu
{
[menu retain];
[fallbackMenu release];
fallbackMenu = menu;
}
It took a double-take until I understood why you'd want to do that. I guess learning Java as my first language was a bad idea.
Oh well. I get it now! 
|
|
|
| |
|
|
|
 |
|
 |
|
Professional Poster
Join Date: Feb 2001
Status:
Offline
|
|
This looks like interesting code.. But what does it do? I am trying to figure out how to make an application (possibly dockling) completely controlled from the dock menu (e.g., one item would be Preferences, another would be About, etc.). Is this code for changing the dock menu?
|
|
The 4 o'clock train will be a bus.
It will depart at 20 minutes to 5.
|
| |
|
|
|
 |
|
 |
|
Senior User
Join Date: Nov 2000
Status:
Offline
|
|
typical usage would be:
Code:
fallback = [[FallbackMenuController alloc] init];
if (![fallback showingIconInDock]) {
[fallback setFallbackMenu: fallbackmenu ]; // outlet to an alt. menu
[fallback showFallbackMenu: @"Eyes"];
}
I've already added it to Eyes.
What it does is check and see if someone added the key-value pair that makes the icon not show up in the dock. If the icon isn't in the dock you don't get your standard menubar either. So, this makes a menu over on the right that can be accessed from anywhere(an always visible menu).
As soon as I get it working I'll email the code back to ya.
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |