Merge pull request #2370 from atom/osx-tray

Use NSImageView to draw tray icon.
This commit is contained in:
Cheng Zhao 2015-07-29 17:22:47 +08:00
commit 80f45f6226

View file

@ -12,8 +12,8 @@
namespace { namespace {
const CGFloat kStatusItemLength = 26; // By default, OS X sets 4px to tray image as left and right padding margin.
const CGFloat kMargin = 3; const CGFloat kHorizontalMargin = 4;
} // namespace } // namespace
@ -24,6 +24,7 @@ const CGFloat kMargin = 3;
BOOL inMouseEventSequence_; BOOL inMouseEventSequence_;
base::scoped_nsobject<NSImage> image_; base::scoped_nsobject<NSImage> image_;
base::scoped_nsobject<NSImage> alternateImage_; base::scoped_nsobject<NSImage> alternateImage_;
base::scoped_nsobject<NSImageView> image_view_;
base::scoped_nsobject<NSString> title_; base::scoped_nsobject<NSString> title_;
base::scoped_nsobject<NSStatusItem> statusItem_; base::scoped_nsobject<NSStatusItem> statusItem_;
} }
@ -37,11 +38,17 @@ const CGFloat kMargin = 3;
isHighlightEnable_ = YES; isHighlightEnable_ = YES;
statusItem_.reset([[[NSStatusBar systemStatusBar] statusItemWithLength: statusItem_.reset([[[NSStatusBar systemStatusBar] statusItemWithLength:
NSVariableStatusItemLength] retain]); NSVariableStatusItemLength] retain]);
CGFloat itemLength = [[statusItem_ statusBar] thickness];
NSRect frame = NSMakeRect(0, NSRect frame = NSMakeRect(0,
0, 0,
kStatusItemLength, itemLength,
[[statusItem_ statusBar] thickness]); itemLength);
if ((self = [super initWithFrame:frame])) { if ((self = [super initWithFrame:frame])) {
image_view_.reset([[[NSImageView alloc] initWithFrame:frame] retain]);
// Unregister image_view_ as a dragged destination, allows its parent view
// (StatusItemView) handle dragging events.
[image_view_ unregisterDraggedTypes];
[self addSubview:image_view_];
[self registerForDraggedTypes: [self registerForDraggedTypes:
[NSArray arrayWithObjects:NSFilenamesPboardType, nil]]; [NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
[statusItem_ setView:self]; [statusItem_ setView:self];
@ -55,44 +62,53 @@ const CGFloat kMargin = 3;
} }
- (void)drawRect:(NSRect)dirtyRect { - (void)drawRect:(NSRect)dirtyRect {
// Draw the tray icon and title that align with NSSStatusItem, layout: // Draw the tray icon and title that align with NSStatusItem, layout:
// ---------------- // ----------------
// | icon | title | // | icon | title |
/// ---------------- /// ----------------
BOOL highlight = [self shouldHighlight]; BOOL highlight = [self shouldHighlight];
CGFloat titleWidth = [self titleWidth]; CGFloat titleWidth = [self titleWidth];
// Calculate the total icon bounds. CGFloat statusItemHeight = [[statusItem_ statusBar] thickness];
CGFloat iconWidth =((highlight && alternateImage_) ?
[alternateImage_ size].width : [image_ size].width) +
2 * kHorizontalMargin;
NSRect iconRect = NSMakeRect(0, 0, iconWidth, statusItemHeight);
// Calculate the total status item bounds.
CGFloat statusItemWidth = iconWidth + titleWidth;
// If title is set, need to add right margin to the title.
if (title_) {
statusItemWidth += kHorizontalMargin;
}
NSRect statusItemBounds = NSMakeRect(0, NSRect statusItemBounds = NSMakeRect(0,
0, 0,
kStatusItemLength + titleWidth, statusItemWidth,
[[statusItem_ statusBar] thickness]); statusItemHeight);
[statusItem_ drawStatusBarBackgroundInRect:statusItemBounds [statusItem_ drawStatusBarBackgroundInRect:statusItemBounds
withHighlight:highlight]; withHighlight:highlight];
[statusItem_ setLength:titleWidth + kStatusItemLength]; [statusItem_ setLength:statusItemWidth];
// Custom ImageView
[image_view_ setFrame: iconRect];
if (highlight && alternateImage_) {
[image_view_ setImage:alternateImage_];
} else {
[image_view_ setImage:image_];
}
if (title_) { if (title_) {
NSRect titleDrawRect = NSMakeRect(kStatusItemLength, NSRect titleDrawRect = NSMakeRect(iconWidth,
0, 0,
titleWidth + kStatusItemLength, statusItemWidth - kHorizontalMargin,
[[statusItem_ statusBar] thickness]); statusItemHeight);
[title_ drawInRect:titleDrawRect [title_ drawInRect:titleDrawRect
withAttributes:[self titleAttributes]]; withAttributes:[self titleAttributes]];
} }
}
NSRect iconRect = NSMakeRect(0, - (BOOL) isDarkMode {
0, return [[[NSAppearance currentAppearance] name] hasPrefix:
kStatusItemLength, NSAppearanceNameVibrantDark];
[[statusItem_ statusBar] thickness]);
if (highlight && alternateImage_) {
[alternateImage_ drawInRect:NSInsetRect(iconRect, kMargin, kMargin)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1];
} else {
[image_ drawInRect:NSInsetRect(iconRect, kMargin, kMargin)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1];
}
} }
- (CGFloat)titleWidth { - (CGFloat)titleWidth {
@ -105,7 +121,8 @@ const CGFloat kMargin = 3;
- (NSDictionary*)titleAttributes { - (NSDictionary*)titleAttributes {
NSFont* font = [NSFont menuBarFontOfSize:0]; NSFont* font = [NSFont menuBarFontOfSize:0];
NSColor* foregroundColor = [NSColor blackColor]; NSColor* foregroundColor =
[self isDarkMode] ? [NSColor whiteColor] : [NSColor blackColor];
return [NSDictionary dictionaryWithObjectsAndKeys: return [NSDictionary dictionaryWithObjectsAndKeys:
font, NSFontAttributeName, font, NSFontAttributeName,