Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cocoa: Right Click NSStatusItem

I am a .Net developer who need to port a small project into Mac, so I know next to nothing about Objective C. In fact the code below was just a bunch of grasping at straws and shooting in the dark.

Trying to build a Status Menu program that opens one or another window depending on if it is a left-click or a right-click/ctrl+click. Here is what I have, and it works for left-click only (obviously):

-(void) awakeFromNib{

    NSBundle *bundle = [NSbundle mainBundle];

    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
    [statusImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"icon" ofType:@"png"]];
    [statusItem setImage:statusImage];
    [statusItem setToolTip:@"Program Name"];
    [statusItem setHighlightMode:YES];
    [statusItem setAction:@selector(openWin:)];
    [statusItem setTarget: self];
}

-(void)openWin:(id)sender{
    [self openLeftWindow:sender];
}

-(IBAction)openLeftWindow:(id)sender{
    //Code to populate Left Click Window
    [leftWindow makeKeyAndorderFront:nil];
}

-(IBAction)openRightWindow:(id)sender{
    //Code to populate Right Click Window
    [rightWindow makeKeyAndorderFront:nil];
}

It seems to me that the solution would be either an if statement in the openWin() function to determine which button is clicked (or if ctrl was held down) then run the appropriate code or to make the menu aware of both the left and right clicks. But neither of these have worked when I attempted to do so.

Thanks In Advance.

like image 301
Dan Avatar asked Dec 30 '10 19:12

Dan


3 Answers

If you will be satisfied with detecting control-click and not right click, then the first block of code will do what you want. If you really need the right click detection, you will have to use a custom view instead of an image in your NSStatusItem, and the second block of code will work.

Simple Method:

- (void)openWin:(id)sender {
    NSEvent *event = [NSApp currentEvent];
    if([event modifierFlags] & NSControlKeyMask) {
        [self openRightWindow:nil];
    } else {
        [self openLeftWindow:nil];
    }
}

Custom view method:

- (void)awakeFromNib {
    ...
    statusImage = ...
    MyView *view = [MyView new];
    view.image = statusImage;
    [statusItem setView:view];
    [statusItem setToolTip:@"Program Name"];
    view target = self;
    view action = @selector(openLeftWindow:);
    view rightAction = @selector(openRightWindow:);
    [view release];
    //[statusImage release]; //If you are not using it anymore, you should release it.
}

MyView.h

#import <Cocoa/Cocoa.h>
@interface MyView : NSControl {
    NSImage *image;
    id target;
    SEL action, rightAction;
}
@property (retain) NSImage *image;
@property (assign) id target;
@property (assign) SEL action, rightAction;
@end

MyView.m

#import "MyView.h"
@implementation MyView
@synthesize image, target, action, rightAction;
- (void)mouseUp:(NSEvent *)event {
    if([event modifierFlags] & NSControlKeyMask) {
        [NSApp sendAction:self.rightAction to:self.target from:self];
    } else {
        [NSApp sendAction:self.action to:self.target from:self];
    }
}
- (void)rightMouseUp:(NSEvent *)event {
    [NSApp sendAction:self.rightAction to:self.target from:self];
}
- (void)dealloc {
    self.image = nil;
    [super dealloc];
}
- (void)drawRect:(NSRect)rect {
    [self.image drawInRect:self.bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}
@end
like image 60
ughoavgfhw Avatar answered Nov 18 '22 09:11

ughoavgfhw


I would create a view and use the status items method.

-setView:

Then in the subclassed view you can detect ctrl+LMB using the following

- (void)mouseDown:(NSEvent *)theEvent
{
    [super mouseDown:theEvent];

    //Respond to the mouse click
    if ([theEvent modifierFlags] & NSCommandKeyMask) //Command + LMB
    {       
      //Do something
    }
}

I think you can figure out the rest.

like image 37
David Avatar answered Nov 18 '22 10:11

David


A more simplified response (Note, only works with control + click)

Properties:

@property (strong, nonatomic) NSStatusItem *statusItem;
@property (weak) IBOutlet NSMenu *statusMenu;

In Your Application Did Load:

[self.statusItem setAction:@selector(itemClicked:)];

Clicked Function:

- (void)itemClicked:(id)sender
{
    NSEvent *event = [NSApp currentEvent];

    if([event modifierFlags] & NSControlKeyMask) {
        NSLog(@"Right Click Pressed");
        [self.statusItem popUpStatusItemMenu:self.statusMenu];

    } else {
        // Do Nothing
        NSLog(@"Left Click Pressed");
    }
}
like image 1
James Marino Avatar answered Nov 18 '22 09:11

James Marino