diff options
author | avi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-17 19:15:22 +0000 |
---|---|---|
committer | avi@google.com <avi@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-17 19:15:22 +0000 |
commit | def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9 (patch) | |
tree | d74d87ef1b5d21d943650db47a1ae3b4f37216cf /chrome/browser | |
parent | e382a69f617ee0c196f7fe4b2f61ba6decd29b29 (diff) | |
download | chromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.zip chromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.tar.gz chromium_src-def8e9a494c0b7fd2034c4cd90d7e9b7c08073e9.tar.bz2 |
First pass at Mac status bubble.
Review URL: http://codereview.chromium.org/48070
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11895 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_window.h | 4 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.h | 6 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.mm | 6 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_bubble_mac.h | 50 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_bubble_mac.mm | 236 |
5 files changed, 300 insertions, 2 deletions
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h index 2151717..b779ba1 100644 --- a/chrome/browser/browser_window.h +++ b/chrome/browser/browser_window.h @@ -29,7 +29,9 @@ class Rect; // NOTE: All getters except GetTabStrip() may return NULL. class BrowserWindow { public: - // Initialize the frame. + // Initialize the frame. This is called on Windows via the views system. It + // doesn't get called on other platforms so don't do stuff here on other + // platforms. virtual void Init() = 0; // Show the window, or activates it if it's already visible. diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h index df1eb42..a74ed8f 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.h +++ b/chrome/browser/cocoa/browser_window_cocoa.h @@ -5,11 +5,14 @@ #ifndef CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_ #define CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_ +#include "base/scoped_ptr.h" #include "chrome/browser/browser_window.h" @class BrowserWindowController; @class NSWindow; +class StatusBubbleMac; + // An implementation of BrowserWindow for Cocoa. Bridges between C++ and // the Cocoa NSWindow. Cross-platform code will interact with this object when // it needs to manipulate the window. @@ -66,6 +69,9 @@ class BrowserWindowCocoa : public BrowserWindow { private: BrowserWindowController* controller_; // weak, owns us NSWindow* window_; // weak, owned by |controller_| + + // The status bubble manager. Always non-NULL. + scoped_ptr<StatusBubbleMac> status_bubble_; }; #endif // CHROME_BROWSER_COCOA_BROWSER_WINDOW_COCOA_H_ diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 1163f1e5..b062a4f 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -6,16 +6,20 @@ #include "base/logging.h" #include "chrome/browser/cocoa/browser_window_cocoa.h" #include "chrome/browser/cocoa/browser_window_controller.h" +#include "chrome/browser/cocoa/status_bubble_mac.h" BrowserWindowCocoa::BrowserWindowCocoa(BrowserWindowController* controller, NSWindow* window) : controller_(controller), window_(window) { + status_bubble_.reset(new StatusBubbleMac(window_)); } BrowserWindowCocoa::~BrowserWindowCocoa() { } void BrowserWindowCocoa::Init() { + // Remember, no code here. This doesn't get called on the Mac. Put code into + // the constructor, above, instead. } void BrowserWindowCocoa::Show() { @@ -61,7 +65,7 @@ BrowserWindowTesting* BrowserWindowCocoa::GetBrowserWindowTesting() { } StatusBubble* BrowserWindowCocoa::GetStatusBubble() { - return NULL; + return status_bubble_.get(); } void BrowserWindowCocoa::SelectedTabToolbarSizeChanged(bool is_animating) { diff --git a/chrome/browser/cocoa/status_bubble_mac.h b/chrome/browser/cocoa/status_bubble_mac.h new file mode 100644 index 0000000..6581ac7 --- /dev/null +++ b/chrome/browser/cocoa/status_bubble_mac.h @@ -0,0 +1,50 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_ +#define CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_ + +#include <string> + +#import <Cocoa/Cocoa.h> + +#include "chrome/browser/status_bubble.h" + +class GURL; + +class StatusBubbleMac : public StatusBubble { + public: + StatusBubbleMac(NSWindow* parent); + virtual ~StatusBubbleMac(); + + // StatusBubble implementation. + virtual void SetStatus(const std::wstring& status); + virtual void SetURL(const GURL& url, const std::wstring& languages); + virtual void Hide(); + virtual void MouseMoved(); + + private: + void SetStatus(NSString* status, bool is_url); + + // Construct the window/widget if it does not already exist. (Safe to call if + // it does.) + void Create(); + + void FadeIn(); + void FadeOut(); + + // The window we attach ourselves to. + NSWindow* parent_; // WEAK + + // The window we own. + NSWindow* window_; + + // The status text we want to display when there are no URLs to display. + NSString* status_text_; + + // The url we want to display when there is no status text to display. + NSString* url_text_; +}; + +#endif // #ifndef CHROME_BROWSER_COCOA_STATUS_BUBBLE_MAC_H_ diff --git a/chrome/browser/cocoa/status_bubble_mac.mm b/chrome/browser/cocoa/status_bubble_mac.mm new file mode 100644 index 0000000..b6b4922 --- /dev/null +++ b/chrome/browser/cocoa/status_bubble_mac.mm @@ -0,0 +1,236 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/cocoa/status_bubble_mac.h" + +#include "base/string_util.h" +#include "base/sys_string_conversions.h" +#include "chrome/common/gfx/text_elider.h" +#include "googleurl/src/gurl.h" +#import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" + +namespace { + +const int kWindowHeight = 18; +// The width of the bubble in relation to the width of the parent window. +const float kWindowWidthPercent = 1.0f/3.0f; + +const int kTextPadding = 3; +const int kTextPositionX = 4; +const int kTextPositionY = 2; + +const float kWindowFill = 0.8f; +const float kWindowEdge = 0.7f; + +// The roundedness of the edges of our bubble. +const int kBubbleCornerRadius = 4.0f; + +// How long each fade should last for. +const int kShowFadeDuration = 0.120f; +const int kHideFadeDuration = 0.200f; + +} + +// TODO(avi): +// - move in response to overlapping mouse +// - do display delay +// - figure out why the show/fade durations aren't working + +@interface StatusBubbleViewCocoa : NSView { + @private + NSString* content_; +} + +- (void)setContent:(NSString*)content; +- (NSFont*)font; +@end + +StatusBubbleMac::StatusBubbleMac(NSWindow* parent) + : parent_(parent), + window_(nil), + status_text_(nil), + url_text_(nil) { +} + +StatusBubbleMac::~StatusBubbleMac() { + Hide(); +} + +void StatusBubbleMac::SetStatus(const std::wstring& status) { + Create(); + + NSString* status_ns = base::SysWideToNSString(status); + + SetStatus(status_ns, false); +} + +void StatusBubbleMac::SetURL(const GURL& url, const std::wstring& languages) { + Create(); + + NSRect frame = [window_ frame]; + int text_width = static_cast<int>(frame.size.width - + kTextPositionX - + kTextPadding); + NSFont* font = [[window_ contentView] font]; + ChromeFont font_chr = + ChromeFont::CreateFont(base::SysNSStringToWide([font fontName]), + [font pointSize]); + + std::wstring status = gfx::ElideUrl(url, font_chr, text_width, languages); + NSString* status_ns = base::SysWideToNSString(status); + + SetStatus(status_ns, true); +} + +void StatusBubbleMac::SetStatus(NSString* status, bool is_url) { + NSString** main; + NSString** backup; + + if (is_url) { + main = &url_text_; + backup = &status_text_; + } else { + main = &status_text_; + backup = &url_text_; + } + + if ([status isEqualToString:*main]) + return; + + [*main release]; + *main = [status retain]; + if ([*main length] > 0) { + [[window_ contentView] setContent:*main]; + } else if ([*backup length] > 0) { + [[window_ contentView] setContent:*backup]; + } else { + Hide(); + } + + FadeIn(); +} + +void StatusBubbleMac::Hide() { + FadeOut(); + + if (window_) { + [parent_ removeChildWindow:window_]; + [window_ release]; + window_ = nil; + } + + [status_text_ release]; + status_text_ = nil; + [url_text_ release]; + url_text_ = nil; +} + +void StatusBubbleMac::MouseMoved() { +} + +void StatusBubbleMac::Create() { + if (window_) + return; + + NSRect rect = [parent_ frame]; + rect.size.height = kWindowHeight; + rect.size.width = static_cast<int>(kWindowWidthPercent * rect.size.width); + // TODO(avi):fix this for RTL + window_ = [[NSWindow alloc] initWithContentRect:rect + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + [window_ setMovableByWindowBackground:NO]; + [window_ setBackgroundColor:[NSColor clearColor]]; + [window_ setLevel:NSNormalWindowLevel]; + [window_ setOpaque:NO]; + [window_ setHasShadow:NO]; + + NSView* view = + [[[StatusBubbleViewCocoa alloc] initWithFrame:NSZeroRect] autorelease]; + [window_ setContentView:view]; + + [parent_ addChildWindow:window_ ordered:NSWindowAbove]; + + [window_ setAlphaValue:0.0f]; + [window_ orderFront:nil]; +} + +void StatusBubbleMac::FadeIn() { + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:kShowFadeDuration]; + [[window_ animator] setAlphaValue:1.0f]; + [NSAnimationContext endGrouping]; +} + +void StatusBubbleMac::FadeOut() { + [NSAnimationContext beginGrouping]; + [[NSAnimationContext currentContext] setDuration:kHideFadeDuration]; + [[window_ animator] setAlphaValue:0.0f]; + [NSAnimationContext endGrouping]; +} + +@implementation StatusBubbleViewCocoa + +- (void)dealloc { + [content_ release]; + [super dealloc]; +} + +- (void)setContent:(NSString*)content { + [content_ autorelease]; + content_ = [content copy]; + [self setNeedsDisplay:YES]; +} + +- (NSFont*)font { + return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]]; +} + +- (void)drawRect:(NSRect)rect { + // Decide on which corners to round + // TODO(avi): decide properly + float tl_radius = 0.0f; + float tr_radius = kBubbleCornerRadius; + float bl_radius = 0.0f; + float br_radius = 0.0f; + + // Background / Edge + + NSRect bounds = [self bounds]; + NSBezierPath *border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds + topLeftCornerRadius:tl_radius + topRightCornerRadius:tr_radius + bottomLeftCornerRadius:bl_radius + bottomRightCornerRadius:br_radius]; + + [[NSColor colorWithDeviceWhite:kWindowFill alpha:1.0f] set]; + [border fill]; + + border = [NSBezierPath gtm_bezierPathWithRoundRect:bounds + topLeftCornerRadius:tl_radius + topRightCornerRadius:tr_radius + bottomLeftCornerRadius:bl_radius + bottomRightCornerRadius:br_radius]; + + [[NSColor colorWithDeviceWhite:kWindowEdge alpha:1.0f] set]; + [border stroke]; + + // Text + + NSFont* textFont = [self font]; + NSShadow* textShadow = [[[NSShadow alloc] init] autorelease]; + [textShadow setShadowBlurRadius:1.5f]; + [textShadow setShadowColor:[NSColor whiteColor]]; + [textShadow setShadowOffset:NSMakeSize(0.0f, -1.0f)]; + + NSDictionary* textDict = [NSDictionary dictionaryWithObjectsAndKeys: + textFont, NSFontAttributeName, + textShadow, NSShadowAttributeName, + nil]; + [content_ drawAtPoint:NSMakePoint(kTextPositionX, kTextPositionY) + withAttributes:textDict]; +} + +@end |