[awake app] 自定义StatusItemView

2014-02-23 16\_43\_29.gif

源码已经放在github

左击切换状态,右击显示菜单;但是NSStatusItem没有提供右键菜单,所以要定义自己的View;若果需要直接方便使用的话,有开源框架RHStatusItemView,引入项目中就可以用了。下面是我自己实现的:

//
//  StatusItemView.h
//  awake
//
//  Created by xiaozi on 14-2-21.
//  Copyright (c) 2014年 xiaozi. All rights reserved.
//

#import <Cocoa/Cocoa.h>

@interface StatusItemView : NSControl <NSMenuDelegate>{
    NSImage *_image;
    NSImage *_alternateImage;
    NSStatusItem *_statusItem;
    BOOL _isHighlighted;
    SEL _action;
    SEL _rightAction;
    id __unsafe_unretained _target;
}

@property (nonatomic, readonly) NSStatusItem *statusItem;
@property (nonatomic, strong) NSImage *image;
@property (nonatomic, strong) NSImage *alternateImage;
@property (nonatomic, setter = setHighlighted:) BOOL isHighlighted;
@property (nonatomic) SEL action;
@property (nonatomic) SEL rightAction;
@property (nonatomic, unsafe_unretained) id target;

- (id) initWithStatusItem: (NSStatusItem *) statusItem;

@end
//
//  StatusItemView.m
//  awake
//
//  Created by xiaozi on 14-2-21.
//  Copyright (c) 2014年 xiaozi. All rights reserved.
//

#import "StatusItemView.h"

@implementation StatusItemView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

- (void) drawRect:(NSRect)dirtyRect
{
    [_statusItem drawStatusBarBackgroundInRect:dirtyRect withHighlight:_isHighlighted];
    NSImage *icon = _isHighlighted ? _alternateImage : _image;
    NSSize iconSize = [icon size];
    NSRect bounds = [self bounds];
    
    CGFloat iconX = roundf((NSWidth(bounds) - iconSize.width) / 2);
    CGFloat iconY = roundf((NSHeight(bounds) - iconSize.height) / 2);
    NSPoint iconPoint = NSMakePoint(iconX, iconY);
    [icon drawAtPoint:iconPoint fromRect:bounds operation:NSCompositeSourceOver fraction:1.0];
}

- (id) initWithStatusItem: (NSStatusItem *) statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    self = [self initWithFrame:itemRect];
    if (self != nil)
    {
        _statusItem = statusItem;
        [_statusItem setView: self];
    }
    return self;
}

- (void)setMenu:(NSMenu *) menu {
    [menu setDelegate: self];
    [super setMenu: menu];
}

- (void)setHighlighted:(BOOL)newFlag
{
    if (_isHighlighted == newFlag) return;
    _isHighlighted = newFlag;
    [self setNeedsDisplay:YES];
}

- (void)mouseDown:(NSEvent *)theEvent
{
    [NSApp sendAction:_action to:_target from:self];
}

- (void)rightMouseDown:(NSEvent *)theEvent
{
    NSMenu *menu = [super menu];
    [_statusItem popUpStatusItemMenu:menu];
    [NSApp sendAction:_rightAction to:_target from:self];
}

- (void)menuWillOpen:(NSMenu *)menu {
    [self setHighlighted:YES];
    [self setNeedsDisplay:YES];
}

- (void)menuDidClose:(NSMenu *)menu {
    [self setHighlighted:NO];
    [self setNeedsDisplay:YES];
}

- (void)setImage:(NSImage *)newImage
{
    _image = newImage;
    [self setNeedsDisplay: YES];
}

- (void)setAlternateImage:(NSImage *)newImage
{
    _alternateImage = newImage;
    if (_isHighlighted)
        [self setNeedsDisplay:YES];
}

- (BOOL)isOpaque
{
    return YES;
}

@end

具体使用方法:

statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength: 22.0];
[statusItem setHighlightMode:YES];
statusView = [[StatusItemView alloc] initWithStatusItem: statusItem];
[statusView setMenu: statusMenu];
// [statusItem setView: statusView];
[statusView setImage: [NSImage imageNamed:@"MenuIcon"]];
[statusView setAlternateImage: [NSImage imageNamed:@"MenuIconSelected"]];

[statusView setAction: @selector(clickStatusItem:)];

标签: none

添加新评论