1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "ui/message_center/cocoa/status_item_view.h"
9 #include "base/format_macros.h"
10 #include "base/mac/sdk_forward_declarations.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/resources/grit/ui_resources.h"
14 // The width of the status bar item when it's just the icon.
15 const CGFloat kStatusItemLength = 26;
17 // The amount of space between the left and right edges and the content of the
19 const CGFloat kMargin = 5;
22 @interface MCStatusItemView (Private)
23 // Whether or not the status item should be drawn highlighted.
24 - (BOOL)shouldHighlight;
26 - (int)getTrayResourceId;
29 @implementation MCStatusItemView
31 @synthesize highlight = highlight_;
34 statusItem_.reset([[[NSStatusBar systemStatusBar] statusItemWithLength:
35 NSVariableStatusItemLength] retain]);
36 CGFloat thickness = [[statusItem_ statusBar] thickness];
38 NSRect frame = NSMakeRect(0, 0, kStatusItemLength, thickness);
39 if ((self = [super initWithFrame:frame])) {
40 [statusItem_ setView:self];
46 [[NSStatusBar systemStatusBar] removeStatusItem:statusItem_];
50 - (size_t)unreadCount {
54 - (message_center::StatusItemClickedCallback)callback {
55 return callback_.get();
58 - (void)setCallback:(message_center::StatusItemClickedCallback)callback {
59 callback_.reset(callback, base::scoped_policy::RETAIN);
62 - (void)setUnreadCount:(size_t)unreadCount withQuietMode:(BOOL)quietMode {
63 unreadCount_ = unreadCount;
64 quietMode_ = quietMode;
66 NSRect frame = [self frame];
67 frame.size.width = kStatusItemLength;
68 [self setFrame:frame];
70 [self setNeedsDisplay:YES];
73 - (void)setHighlight:(BOOL)highlight {
74 highlight_ = highlight;
75 [self setNeedsDisplay:YES];
78 - (void)mouseDown:(NSEvent*)event {
79 inMouseEventSequence_ = YES;
80 [self setNeedsDisplay:YES];
86 - (void)mouseUp:(NSEvent*)event {
87 inMouseEventSequence_ = NO;
88 [self setNeedsDisplay:YES];
91 - (void)rightMouseDown:(NSEvent*)event {
92 [self mouseDown:event];
95 - (void)rightMouseUp:(NSEvent*)event {
99 - (void)otherMouseDown:(NSEvent*)event {
100 [self mouseDown:event];
103 - (void)otherMouseUp:(NSEvent*)event {
104 [self mouseUp:event];
107 - (void)drawRect:(NSRect)dirtyRect {
108 NSRect frame = [self bounds];
110 // Draw the background color.
111 BOOL highlight = [self shouldHighlight];
112 [statusItem_ drawStatusBarBackgroundInRect:frame
113 withHighlight:highlight];
115 int resource_id = [self getTrayResourceId];
117 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
118 NSImage* image = rb.GetNativeImageNamed(resource_id).ToNSImage();
119 NSSize size = [image size];
120 NSRect drawRect = NSMakeRect(kMargin,
121 floorf((NSHeight(frame) - size.height) / 2),
124 [image drawInRect:drawRect
126 operation:NSCompositeSourceOver
130 - (NSArray*)accessibilityActionNames {
131 return @[ NSAccessibilityPressAction ];
134 - (void)accessibilityPerformAction:(NSString*)action {
135 if ([action isEqualToString:NSAccessibilityPressAction]) {
140 [super accessibilityPerformAction:action];
143 // Private /////////////////////////////////////////////////////////////////////
145 - (BOOL)shouldHighlight {
146 return highlight_ || inMouseEventSequence_;
149 - (int)getTrayResourceId {
150 BOOL highlight = [self shouldHighlight];
151 BOOL hasUnreadItems = unreadCount_ > 0;
154 Class nsAppearanceClass = NSClassFromString(@"NSAppearance");
155 if ([self respondsToSelector:@selector(effectiveAppearance)] &&
156 [nsAppearanceClass respondsToSelector:@selector(appearanceNamed:)]) {
157 id<NSObject> darkAppearance =
158 [nsAppearanceClass appearanceNamed:NSAppearanceNameVibrantDark];
159 dark = [[self effectiveAppearance] isEqual:darkAppearance];
162 int kResourceIds[2][2][2][2] = {
165 { IDR_TRAY_EMPTY, IDR_TRAY_EMPTY_PRESSED },
166 { IDR_TRAY_ATTENTION, IDR_TRAY_ATTENTION_PRESSED },
169 { IDR_TRAY_DO_NOT_DISTURB_EMPTY,
170 IDR_TRAY_DO_NOT_DISTURB_EMPTY_PRESSED },
171 { IDR_TRAY_DO_NOT_DISTURB_ATTENTION,
172 IDR_TRAY_DO_NOT_DISTURB_ATTENTION_PRESSED },
177 // We chose not to support the empty version of the pressed
178 // resource for the dark theme, so we use the same resource
179 // for both "pressed" options.
180 { IDR_DARK_TRAY_EMPTY, IDR_DARK_TRAY_PRESSED },
181 { IDR_DARK_TRAY_ATTENTION, IDR_DARK_TRAY_PRESSED },
184 { IDR_DARK_TRAY_DO_NOT_DISTURB_EMPTY,
185 IDR_DARK_TRAY_DO_NOT_DISTURB_PRESSED },
186 { IDR_DARK_TRAY_DO_NOT_DISTURB_ATTENTION,
187 IDR_DARK_TRAY_DO_NOT_DISTURB_PRESSED },
191 return kResourceIds[dark][quietMode_][hasUnreadItems][highlight];